c# - ¿Cómo forzar la actualización de errores de validación en View from ViewModel usando IDataErrorInfo?
wpf validation (3)
Este ''Hack'' funcionó temporalmente para mí, para forzar el evento InotifyChanged, simplemente asigne a ese control su propio contenido. Haga esto antes de evaluar la función HasError de los enlaces. Por ejemplo, un cuadro de texto sería:
((TextBox)child).Text = ((TextBox)child).Text;
Y luego, un ejemplo completo (antes de que escuche que esto no es MVVM verdadero, obtuve directamente un identificador en la cuadrícula para facilitar la visualización de este fragmento de código)
public bool Validate()
{
bool hasErr = false;
for (int i = 0; i != VisualTreeHelper.GetChildrenCount(grd); ++i)
{
DependencyObject child = VisualTreeHelper.GetChild(grd, i);
if (child is TextBox)
{
bool pp = BindingOperations.IsDataBound(child, TextBox.TextProperty);
if (pp)
{
((TextBox)child).Text = ((TextBox)child).Text;
hasErr = BindingOperations.GetBindingExpression(child, TextBox.TextProperty).HasError;
System.Collections.ObjectModel.ReadOnlyCollection<ValidationError> errors = BindingOperations.GetBindingExpression(child, TextBox.TextProperty).ValidationErrors;
if (hasErr)
{
main.BottomText.Foreground = Brushes.Red;
main.BottomText.Text = BindingOperations.GetBinding(child, TextBox.TextProperty).Path.Path.Replace(''.'', '' '') + ": " + errors[0].ErrorContent.ToString();
return false;
}
}
}
if (child is DatePicker)
{
...
}
}
return true;
}
Tengo una ventana basada en MVVM con muchos controles, y mi modelo implementa IDataErrorInfo
.
También hay un botón SaveCommand
, que realiza la validación mediante el análisis de la propiedad Model.Error
.
La vista muestra el borde rojo predeterminado alrededor de los controles con errores solo cuando cambio el valor de un control en particular, o cuando notifico sobre el cambio de esa propiedad usando PropertyChanged.
¿Cómo puedo forzar la vista para mostrar todos los errores de validación incluso cuando no toqué los controles?
Todos mis enlaces de validación incluyen ValidatesOnDataErrors=True, NotifyOnValidationError=True
.
Sé que una solución es tener una caja agregada con todos los errores, pero preferiría mostrar los errores por control.
No quiero activar Model.NotifyPropertyChanged
para cada propiedad vinculada desde ViewModel.
Yo uso WPF 4.0, no Silverlight, por lo que INotifyDataErrorInfo
no funcionará.
La mejor solución que he encontrado hasta ahora que funciona es cambiar DataContext a nulo y volver a la instancia de ViewModel.
Esto activa la actualización de los controles en la vista que tiene DataContext
enlazado a InnerViewModel
:
public void ForceUpdateErrors() {
var tmpInnerVM = _mainViewModel.InnerViewModel;
_mainViewModel.InnerViewModel = null;
_mainViewModel.InnerViewModel = tmpInnerVM;
}
Se recomienda verificar si no se pierden datos después de este truco. Tuve un caso de que este código activaba la actualización de la fuente para ComboBox.SelectedItem con un valor nulo pero logré resolverlo. Fue causado por el uso de un BindingProxy basado en recursos y el orden de DataContext=null
propagación DataContext=null
toda la jerarquía de control.
Menciona que no desea aumentar la propiedad modificada para las propiedades a las que se enlaza, pero esa es realmente la forma más sencilla de lograrlo. Llamar a PropertyChanged sin ningún parámetro aumentará para todas las propiedades en su modelo de vista.
Alternativamente, puede actualizar los enlaces (y forzar la revalidación) en cualquier control como este:
myControl.GetBindingExpression(ControlType.ControlProperty).UpdateSource();