Wpf 第一次加载时的验证绑定
我仍然在努力验证WPF 我有一个自定义的验证规则,它要求文本出现在文本框中,即它强制执行强制字段约束Wpf 第一次加载时的验证绑定,wpf,validation,binding,Wpf,Validation,Binding,我仍然在努力验证WPF 我有一个自定义的验证规则,它要求文本出现在文本框中,即它强制执行强制字段约束 <TextBox local:Masking.Mask="^[a-zA-Z0-9]*$" x:Name="CameraIdCodeTextBox" Grid.Row="1" Grid.Column="1"> <Binding Path="CameraIdCode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" Not
<TextBox local:Masking.Mask="^[a-zA-Z0-9]*$" x:Name="CameraIdCodeTextBox" Grid.Row="1" Grid.Column="1">
<Binding Path="CameraIdCode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<localValidation:RequiredFieldRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
问题是,当窗口第一次加载时,文本框中没有文本(正如您所期望的)。但是Text属性被绑定到ViewModel上的一个属性,因此,验证规则正在启动,这表明窗口存在问题——甚至在用户有机会违反业务规则之前
这是以前解决过的问题吗?我不可能是第一个体验到这一点的人。我相信这对年轻球员来说是个陷阱。这有几种模式。我通常在类/模型上实现
ISupportInitialize
接口,这将要求您创建BeginInit()
和EndInit()
,在这些方法中,我只需将私有bool设置为true或false
在视图模型中,或在何处/何时创建/填充模型/类,使用begin和end init将其包装:
var o = new SampleObject();
o.BeginInit()
o.StartDate = DateTime.Now; //just some sample property...
o.EndInit();
因此,根据ValidationRule的调用方式,您可以检查\u初始化的状态,查看是否需要验证
最近我一直在使用属性验证器,该验证器在PropertyChanged
上启动,因此您可以执行以下操作:
[CustomValidator("ValidateStartDate")]
public DateTime StartDate
{ get ...
{
set
{
if(_startDate == value) return;
_startDate = value;
if(_isInitializing) return;
RaisePropertyChange(() => StartDate);
}..
如果您不想为ISupportInitialize
而烦恼,那么在构建过程中传递属性中所需的所有值,而不是属性。绑定将第一次查询属性的getter并获取它们的值,然后通过属性setter进行验证:
//c-tor
public MyObject(DateTime start)
{
_startDate = start;
}
已经有一段时间了,我应该更新这个问题。我用Ian Griffths(一本O'Reilly的书)在WPF书中找到的一个类解决了这个问题:
公共静态类验证程序
{
///
///此方法强制WPF验证作为参数传入的控件的子控件。
///
///类型:DependencyObject。要验证的子代根控件。
///类型:bool。验证结果
公共静态bool有效(DependencyObject父对象)
{
//验证父级上的所有绑定
bool valid=true;
LocalValueEnumerator localValues=parent.GetLocalValueEnumerator();
while(localValues.MoveNext())
{
LocalValueEntry=localValues.Current;
if(BindingOperations.IsDataBound(父项,entry.Property))
{
Binding Binding=BindingOperations.GetBinding(父项,entry.Property);
foreach(binding.ValidationRules中的ValidationRule规则)
{
ValidationResult=rule.Validate(parent.GetValue(entry.Property),null);
如果(!result.IsValid)
{
BindingExpression=BindingOperations.GetBindingExpression(父项,entry.Property);
Validation.MarkInvalid(表达式,新的ValidationError(规则,表达式,result.ErrorContent,null));
有效=错误;
}
}
}
}
//验证子节点上的所有绑定
for(int i=0;i!=VisualTreeHelper.GetChildrenCount(父项);+i)
{
DependencyObject子对象=VisualTreeHelper.GetChild(父对象,i);
如果(!IsValid(子项))
{
有效=错误;
}
}
返回有效;
}
}
然后,在视图上,我有以下配置:
<TextBox local:Masking.Mask="^[0-9]*$" IsEnabled="{Binding Path=LocationNumberEnabled}" Grid.Row="1" Grid.Column="3">
<Binding Path="LocationNumber" Mode="TwoWay" UpdateSourceTrigger="LostFocus" NotifyOnValidationError="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<localValidation:PositiveNumberRule />
<localValidation:RequiredFieldRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
工作得很有魅力!每次我想手动验证时,例如在按下按钮时,我都会调用IsValid方法。你能试试。。。UpdateSourceTrigger=“LostFocus”您可以创建一个验证组,并且只能在用户第一次更改某个字段时启用它。@AngelWPF我已经尝试过了。当窗口加载时,它仍然在初始绑定上进行验证。@VladimirPerevalov是否可以启用和禁用绑定?如果是,我可能应该在第一次加载时禁用绑定。但我如何启用它?捕捉用户第一次变更的逻辑,与未来的每一次变更不同,应该是相当复杂的。我不知道为什么一个简单的RequiredField验证器如此困难;初始绑定时不会调用as集合。或者可能在验证中允许string.empty,但在集合中拒绝string.empty;(并抛出验证错误)。
<TextBox local:Masking.Mask="^[0-9]*$" IsEnabled="{Binding Path=LocationNumberEnabled}" Grid.Row="1" Grid.Column="3">
<Binding Path="LocationNumber" Mode="TwoWay" UpdateSourceTrigger="LostFocus" NotifyOnValidationError="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<localValidation:PositiveNumberRule />
<localValidation:RequiredFieldRule />
</Binding.ValidationRules>
</Binding>
</TextBox>