How to force validation errors update on View from ViewModel using IDataErrorInfo?

人走茶凉 提交于 2019-12-05 00:26:02

You mention that you don't want to raise property changed for the properties you bind to, but that's really the simplest way to accomplish this. Calling PropertyChanged with no parameter will raise for all properties in your viewmodel.

Alternatively you can update the bindings (and force revalidation) on any control like this:

myControl.GetBindingExpression(ControlType.ControlProperty).UpdateSource();

The best solution I've found so far that works is to change DataContext to null and back to the instance of ViewModel.

This triggers the update for controls on the view that has DataContext bound to InnerViewModel:

public void ForceUpdateErrors() {
    var tmpInnerVM = _mainViewModel.InnerViewModel;
    _mainViewModel.InnerViewModel = null;
    _mainViewModel.InnerViewModel = tmpInnerVM;
}

It's recommended to check if no data is lost after this trick. I had a case that this code triggered source update for ComboBox.SelectedItem with null but I managed to solve it. It was caused by using a resource-based BindingProxy and the order of DataContext=null propagation across control hierarchy.

This 'Hack' worked for me temporarily, to force the InotifyChanged event, just assign that control back it's own content. Do this before evaluating the HasError function of bindings. For example a textbox would be:

 ((TextBox)child).Text = ((TextBox)child).Text;

And then a complete example(before I hear this is not true MVVM, I directly got a handle on the grid for ease of showing this code snipet)

        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;
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!