WPF, property in ValidationRule never set
I'm trying to bind a property in my DataContext
to a property in a ValidationRule
:
public class ReleaseValidationRule : ValidationRule
{
// I want to bind a value from my DataContext to this property:
public CheckboxViewModels ValidReleases { get; set; }
...
}
Based on this thread, I created the CheckboxViewModels
class just to act as a wrapper for a List<Chec开发者_如何学编程kboxViewModel>
so that the list could be a DependencyProperty
so that I could bind to it. However, in my Validate
method on my ValidationRule
, the ValidReleases
list is always empty. Here's my XAML:
<TextBox>
<TextBox.Text>
<Binding Path="Release" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ReleaseValidationRule>
<local:ReleaseValidationRule.ValidReleases>
<local:CheckboxViewModels List="{Binding Path=Releases,
Converter={StaticResource debugConverter}}"/>
</local:ReleaseValidationRule.ValidReleases>
</local:ReleaseValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
I know the Releases
property (what I'm binding to the List
property of CheckboxViewModels
) has content because I have a TreeView
just above the TextBox
that shows the contents of Releases
. The converter I have on the CheckboxViewModels.List
binding does nothing, it's just a place where I can set a breakpoint. The funny thing is, that converter breakpoint never gets hit. It's as if the whole line <local:CheckboxViewModels List="{Binding Path=Releases, Converter={StaticResource debugConverter}}"/>
never gets executed, so the ValidReleases
property in my ValidationRule
never gets set. What's going on?
Edit: here's what CheckboxViewModels
looks like:
public class CheckboxViewModels : DependencyObject, IList<CheckboxViewModel>,
IEnumerable<CheckboxViewModel>
{
...members necessary to implement IList, IEnumerable...
public static readonly DependencyProperty ListProperty =
DependencyProperty.Register(
"List",
typeof(List<CheckboxViewModel>),
typeof(CheckboxViewModels),
new PropertyMetadata(new List<CheckboxViewModel>())
);
public List<CheckboxViewModel> List
{
get { return (List<CheckboxViewModel>)GetValue(ListProperty); }
set { SetValue(ListProperty, value); }
}
}
Smells like a missing Property Changed notification somewhere. Hard to see what CheckboxModels is about from this, but if it were ObservableCollection you'd get property changed without any extra work. Does this make sense?
HTH,
Berryl
Okay, now I just feel silly. I had had a constructor in CheckboxViewModels
that set List = new List<CheckboxViewModel>()
. I think this was somehow resetting something? I removed that constructor and the initial value of List
is set only in the Register
method for the DependencyProperty
: new PropertyMetadata(new List<CheckboxViewModel>())
. ValidReleases
is now populated as expected with the following XAML:
<TextBox>
<TextBox.Text>
<Binding Path="Release" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ReleaseValidationRule ValidatesOnTargetUpdated="True">
<local:ReleaseValidationRule.ValidReleases>
<local:CheckboxViewModels
List="{Binding Path=Releases, Mode=OneWay}"/>
</local:ReleaseValidationRule.ValidReleases>
</local:ReleaseValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Edit: not so silly afterall: not having a constructor in CheckboxViewModels
resulted in two dependency properties of type CheckboxViewModels
using the same list, so I had releases and other data in both the Releases
property and another property. Adding the constructor back to CheckboxViewModels
results in ValidReleases
not having any items again. I think I must be binding something incorrectly.
I stopped using validation rules and instead followed this tutorial about implementing IDataErrorInfo
. That was my class instance is fully initialized by the time I get into this[string]
to figure out the error message. The data I had been trying to pass in was just data from another property on the same instance. That is, I wanted to validate Property1
using some data from Property2
. With IDataErrorInfo
, when I'm validating Property1
and assembling an error message if necessary, I have access to Property2
as desired, without having to pass anything in.
精彩评论