2017-02-03 4 views
19

После завершения настройки MVVM Light в приложении Universal App для Windows у меня есть следующая структура, и мне интересно, что является самым чистым способом проверки в 2017 году с использованием UWP и mvvmlight для уведомлять пользователей об ошибках и, возможно, сбросить значение текстового поля, когда это необходимо. Единственный трюк в том, что текстовое поле является частью UserControl (для ясности очищено ненужный код xaml), поскольку он будет использоваться несколько раз. Также я добавил DataAnnotations и ValidationResult для демонстрации и не предполагал, что это лучший способ сделать это, или что он работает каким-либо образом до сих пор.Проверка с использованием MVVM Light в универсальном приложении Windows

код работает отлично, насколько обязательными и добавление и удаление значений

  • ViewModel

    using GalaSoft.MvvmLight; 
    using GalaSoft.MvvmLight.Command; 
    using GalaSoft.MvvmLight.Views; 
    using System; 
    using System.ComponentModel.DataAnnotations; 
    
    public class ValidationTestViewModel : ViewModelBase 
    { 
        private int _age; 
    
        [Required(ErrorMessage = "Age is required")] 
        [Range(1, 100, ErrorMessage = "Age should be between 1 to 100")] 
        [CustomValidation(typeof(int), "ValidateAge")] 
        public int Age 
        { 
         get { return _age; } 
         set 
         { 
         if ((value > 1) && (value =< 100)) 
          _age= value; 
         } 
        } 
    
        public static ValidationResult ValidateAge(object value, ValidationContext validationContext) 
        { 
         return null; 
        } 
    } 
    
  • Посмотреть

    <Page 
    x:Class="ValidationTest.Views.ValidationTestPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:ValidationTest.Views" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    DataContext="{Binding ValidationTestPageInstance, Source={StaticResource Locator}}" 
    xmlns:views="using:ValidationTest.Views"> 
    
        <views:NumberEdit TextInControl="{Binding Age, Mode=TwoWay}" /> 
    
    </Page> 
    
  • UserControl

    <UserControl 
    x:Class="ValidationTest.Views.Number" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:ValidationTest.Views" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    x:Name="userControl1"> 
        <Grid> 
    
        <TextBox x:Name="content" Text="{Binding TextInControl, ElementName=userControl1, Mode=TwoWay}"></TextBox> 
        </Grid> 
    
    </UserControl> 
    
  • UserControl Код За:

    public partial class NumberEdit : UserControl 
    { 
        public string TextInControl 
         { 
         get { return (string)GetValue(TextInControlProperty); } 
         set { 
           SetValue(TextInControlProperty, value); 
          } 
    } 
    
    public static readonly DependencyProperty TextInControlProperty = 
        DependencyProperty.Register("TextInControl", typeof(string), 
                typeof(NumberEdit), new PropertyMetadata(null)); 
    
    } 
    

ответ

2

Мы обычно используем IDialogService интерфейс в MVVM Light для уведомления пользователей с ошибками, есть ShowError метод, ShowMessage метод и ShowMessageBox метод в IDialogService.

Мы должны иметь возможность нового экземпляра PropertyMetadata с значением PropertyChangedCallback, он будет вызываться, когда изменяется значение свойства свойства свойства зависимостей. Когда он вызывается, мы можем использовать метод ShowMessage.

Например:

public sealed partial class NumberEdit : UserControl 
{ 
    public NumberEdit() 
    { 
     this.InitializeComponent(); 
    } 

    public static readonly DependencyProperty TextInControlProperty = 
    DependencyProperty.Register("TextInControl", typeof(string), 
            typeof(NumberEdit), new PropertyMetadata(null, new PropertyChangedCallback(StringChanged))); 

    private static void StringChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     int value; 
     Int32.TryParse(e.NewValue.ToString(), out value); 
     if (0 < value && value < 99) 
     { 
     } 
     else 
     { 
      var dialog = ServiceLocator.Current.GetInstance<IDialogService>(); 
      dialog.ShowMessage("Age should be between 1 to 100", "Error mesage"); 
     } 
    } 

    public string TextInControl 
    { 
     get { return (string)GetValue(TextInControlProperty); } 
     set 
     { 
      SetValue(TextInControlProperty, value); 
     } 
    } 
} 

Кроме того, если вы хотите сбросить значение TextBox, вы должны быть в состоянии использовать RaisePropertyChanged в собственности Age. Если мы не используем RaisePropertyChanged в свойстве Age, значение TextBox не изменится при изменении значения Age.

Для получения дополнительной информации о RaisePropertyChanged, пожалуйста, обратитесь к INotifyPropertyChanged interface.

Например:

public int Age 
{ 
    get { return _age; } 
    set 
    { 
     if ((value > 1) && (value <= 100)) 
      _age = value; 
     RaisePropertyChanged("Age"); 
    } 
} 

Update:

В вашей странице Вы должны добавить, чтобы добавить DataContext под вашим контролем.

<Page x:Class="Validation_Using_MVVM_Light_in_a.SecondPage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d" 
     xmlns:local="using:Validation_Using_MVVM_Light_in_a" 
xmlns:VM="using:Validation_Using_MVVM_Light_in_a.ViewModel"> 

    <Page.Resources> 
     <VM:ValidationTestViewModel x:Key="MyViewModel" /> 
    </Page.Resources> 
    <Grid> 
     <local:NumberEdit DataContext="{StaticResource MyViewModel}" TextInControl="{Binding Age, Mode=TwoWay}" /> 
    </Grid> 
</Page> 
+0

Есть ли какие-либо изменения должны быть сделаны в XAML? Кроме того, ссылка PropertyChangedCallback не работает – usefulBee

+1

просто fyi, обе ссылки работают на меня –

+0

@usefulBee Вы должны иметь возможность добавлять DataContext на страницу или элемент управления, также я обновил код в методе StringChanged. –

0

Что вам не хватает здесь, это вызов Validator.ValidateObject, чтобы выполнить фактическую проверку. Это применит атрибуты проверки к данным и также вызовет IValidatableObject.Validate, если вы его внедрили (вы должны реализовать это вместо наличия специальных функций, таких как ValidateAge).

Как это:

 // Validate using: 
     // 1. ValidationAttributes attached to this validatable's class, and 
     // 2. ValidationAttributes attached to the properties of this validatable's class, and 
     // 3. this.Validate(validationContext) 
     // 
     // Note, for entities, a NotSupportedException will be thrown by TryValidateObject if any of 
     // the primary key fields are changed. Correspondingly the UI should not allow modifying 
     // primary key fields. 
     ValidationContext validationContext = new ValidationContext(this); 
     List<ValidationResult> validationResults = new List<ValidationResult>(64); 
     bool isValid = Validator.TryValidateObject(this, validationContext, validationResults, true); 
     Debug.Assert(isValid == (validationResults.Count == 0));