I'm working on a custom validator binding thing. I use multiple validator classes in an UWP project. These validators are custom implementations without any interface and I want to bind the IsValid
property of the validators. My goal is to avoid creating read only proxy properties in the VM to use binding functionality, I want to use dictionary to store and read validators from one property only.
This is my validator class:
public class Validator : ModelValidator<Model>
{
...
}
The base class contains the IsValid
property which needs to be bound.
public class ModelValidator<Model> : INotifyPropertyChanged
{
...
private bool _isValid;
public bool IsValid
{
get { return _isValid; }
set { SetField(ref _isValid, value); }
}
}
Currently I have to create read only properties for each validators.
public class VM : INotifyPropertyChanged
{
...
public Validator Validator
{
get { return Validators['Validator']; } // I can add key check to avoid exception.
}
}
And use the created proxy property for binding.
<TextBlock Visibility={Binding Validator.IsValid} />
To avoid creating proxy properties I found this solution which works, but I cannot trigger the PropertyChanged event to refresh the binding.
<TextBlock Visibility={x:Bind ((local:VM)DataContext).Validators['Validator'].IsValid} />
If I use the built-in dictionary it throws exception when validator does not exist. So it works only if I create and put the validators into the dictionary before the binding execution (in VM constructor).
The second version is a little bit messy but I had to avoid the Dictionary's default indexer logic to avoid exception regarding item is not in the dictionary yet. It allows to add validator later in the VM logic (init, etc.).
public class MyDictionary : Dictionary<string, IValidator>
{
public new IValidator this[string key]
{
get { return Get(key); }
...
}
public IValidator Get(string key)
{
IValidator o;
if (TryGetValue(key, out o))
{
return o;
}
return null;
}
}
This version also selects the correct validator and validator can be created later but I don't need the whole validator for the binding but only its IsValid
property.
<TextBlock Visibility={{Binding Validators, Converter={StaticResource ValidatorSelectionConverter}, ConverterParameter=Validator}} />
Is it possible to use validators in a dictionary and get binding to work? What should I change/add in my code to get full solution?
The problem was that I had to add the Mode="TwoWay" binding option explicitly then it works.
<TextBlock Visibility={x:Bind ((local:VM)DataContext).Validators['Validator'].IsValid, Mode="TwoWay"} />