c# - commandmanager - Validación usando MVVM Light en una aplicación universal de Windows
command mvvm c# (2)
Lo que falta aquí es una llamada a Validator.ValidateObject para hacer la validación real. Esto aplicará los atributos de validación a los datos y también llamará IValidatableObject.Validate si lo ha implementado (debe implementarlo en lugar de tener funciones ad-hoc como ValidateAge).
Me gusta esto:
// 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));
Después de configurar MVVM Light en una aplicación de aplicación universal de Windows, tengo la siguiente estructura y me pregunto cuál es la forma más limpia de validar en 2017 utilizando UWP y mvvmlight para notificar a los usuarios con errores y, posiblemente, restablecer el valor del cuadro de texto cuando sea necesario. . El único truco es que el cuadro de texto es parte de un UserControl (limpiado el código xaml innecesario para mayor claridad) ya que se usará varias veces. También agregué DataAnnotations y ValidationResult para demostración y no sugiero que esta sea la mejor manera de hacerlo o que esté funcionando de alguna manera hasta ahora.
El código funciona bien en lo que respecta a vincular, agregar y eliminar valores
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; } }
Ver
<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>
Control de usuario
<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>
Código de UserControl detrás :
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)); }
Normalmente usamos la interfaz IDialogService
en MVVM Light para notificar a los usuarios con errores, existen el método ShowMessage
, el método ShowMessageBox
y el método IDialogService
en IDialogService
.
Deberíamos poder crear una nueva instancia de PropertyMetadata con un valor PropertyChangedCallback , se invocará cuando cambie el valor de propiedad efectivo de una propiedad de dependencia. Cuando se invoca, podemos usar el método ShowMessage
en él.
Por ejemplo:
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);
}
}
}
Además, si desea restablecer el valor de TextBox
, debería poder usar RaisePropertyChanged
en la propiedad Age. Si no usamos RaisePropertyChanged
en la propiedad Age, el valor de TextBox no cambiará cuando el valor de Age haya cambiado.
Para obtener más información sobre RaisePropertyChanged, consulte la interfaz de INotifyPropertyChanged .
Por ejemplo:
public int Age
{
get { return _age; }
set
{
if ((value > 1) && (value <= 100))
_age = value;
RaisePropertyChanged("Age");
}
}
Actualizar:
En su página debe agregarse para agregar DataContext en su control.
<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>