wpfvalidationadorneradornerlayer

Initial validation on dynamically added control


WPF validation system performs intial validatation of an object (I mean - all fields are validated when a databound item is changed, and results are displayed on the ui). But it doesn't work like this, when I add a control dynamically. In such case inital validation happens, but results aren't shown on the ui. Only after some properties on a databound object change, everything starts working correctly. Here's a crude sample.

Suppose we have MyObject class

 public class MyObject : INotifyPropertyChanged, IDataErrorInfo
 {
    public string Name { /*get, set implementation */}        

    // IDataErrorInfo
    public string this[string columnName]
    {
        get
        {
            if (String.IsNullOrEmpty(Name)) return "Name can't be empty!";
            return String.Empty;
        }
    }
    /* etc. */
}

And some user control, say MyUserControl, that allows editing of MyObject objects. It can look somehow like this:

<UserControl x:Class="Test.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Name: "/>
            <TextBox Text="{Binding Name, ValidatesOnDataErrors=True}" Width="200"/>
        </StackPanel>
</UserControl>

Now, when this control is added to the main window in xaml (or in code behind in constructor or window loaded event) than when MyCustomControl.DataContext is set to a new instance of the MyObject class, the Name field is validated immediately and error notification is displayed using validation error template. But when MyCustomControl is added dynamically (after, say, button is clicked), initial validation happens but ui doesn't show results (no red border etc.)

Suppose that application window consist of a dockpanel (dockPanel) and a button:

public Window1()
        {
            InitializeComponent();

            button.Click +=new RoutedEventHandler(OnButtonClick);

            /*
            // in this case validation works correctly,
            // when window is shown Name textbox already got a red border etc.
            var muc = new MyUserControl();
            dockPanel.Children.Add(muc);
            muc.DataContext = new MyObject(); 
            */
        }


        private void OnButtonClick(object sender, RoutedEventArgs e)
        {
            // in this case validatation works, but no results are shown on the ui
            // only after Name property is changed (then removed again) red border appears
            var muc = new MyUserControl();
            dockPanel.Children.Add(muc);
            muc.DataContext = new MyObject(); 
        }

Why?


Solution

  • Ok, I found kind of an answer. That's problem with adorner layer. Our WPF gurus already encountered it and provided some solution. See Karl Shifflett's post.