简体   繁体   中英

Validating dependency property with INotifyDataErrorInfo

I have a usercontrol with a single Textbox inside a grid like this:

<TextBox Text="{Binding Username}"></TextBox>

The code-behind of the usercontrol implements INotifyDataErrorInfo and INotifyPropertyChanged . This is how my code-behind looks like (Apart from the above mentioned interface implementations)

public TestControl()
{
    InitializeComponent();
    this.DataContext = this;
}

private string _username;
public string Username
{
    get { return _username; }
    set
    {
        _username = value;
        if (_username.Length < 3)
            SetErrors("Username", new List<string> { "Usernames should be at least 3 characters long" });
        OnPropertyChanged("Username");
    }
}

Where SetErrors is just a function which adds an error to the IEnumerable which the INotifyDataErrorInfo.GetErrors will return. This works pretty well. When I write text less than 3 characters, the textbox turns red. That is exactly what I expect.

Now I want the MainWindow's viewmodel to set this textbox. To do that, the Username field should be a dependency property so I can bind to it. But the problem is that I can't validate it now. I made a dependency property and tried validating it at the ValidateValueCallback but INotifyDataErrorInfo members are not static. So I can't reach them. What should I do?

Place Username within MainViewModel and inside of UserControl bind to it using RelativeSource binding like

"{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.Username}"

You can replace explicit name indication with CallerMemberName attribute.

EDIT
When you define dependency property you can determine event which will be raised whenever value's change occurs. As a parameter it has reference to class, in which it is defined, as far as your project is concerned it would be your UserControl. You can then invoke any method on this object, no need to be static at all. Following code depicts the concept, not precise solution, adjust it to your requirement:

   public static readonly DependencyProperty PropertyTypeProperty = DependencyProperty.Register(
        "PropertyType", typeof (propertyType), typeof (PasswordBoxDP), new PropertyMetadata((x, y) =>
        {
            var userControlClass = x as UserControlClass;
            userControlClass.Validate();
        }));

    private void Validate()
    {

    }

By the way, binding in your case will not be working. You defined DataContext refering to itself so when you set a binding on your dependency property it will kick off seeking within UserControl.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM