WPF:绑定到验证规则的 DependencyProperty
WPF: Binding to validation rule's DependencyProperty
我想根据标准规则验证文本框值,其中一对是最小值和最大值。问题是,我需要配置这个值(例如在设置文件中)。
我有验证规则:
public class TextBoxWithIntegerValidation : ValidationRule
{
private Int32RangeChecker _validRange;
public Int32RangeChecker ValidRange
{
get { return _validRange; }
set { _validRange = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var str = value as string;
if (str == null)
{
return new ValidationResult(false, Resources.TextResources.TextBoxIsEmpty_ErrorMessage);
}
int intValue = -1;
if (!int.TryParse(str, out intValue))
{
return new ValidationResult(false, Resources.TextResources.TextBoxNotIntegerValue_ErrorMessage);
}
if (intValue < ValidRange.Minimum)
{
return new ValidationResult(false,
string.Format(Resources.TextResources.TextBoxValueLowerThanMin_ErrorMessage, ValidRange.Minimum));
}
return new ValidationResult(true, null);
}
}
整数范围检查器:
public class Int32RangeChecker : DependencyObject
{
public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(0));
public int Maximum
{
get { return (int)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(100));
}
以及文本框验证:
<TextBox>
<TextBox.Text>
<Binding Path="Interval" UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<validationRules:TextBoxWithIntegerValidation>
<validationRules:TextBoxWithIntegerValidation.ValidRange>
<validationRules:Int32RangeChecker
Minimum="{Binding IntervalMinValue}"
/>
</validationRules:TextBoxWithIntegerValidation.ValidRange>
</validationRules:TextBoxWithIntegerValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
TextBox 放置在 UserControl 中,适当的 ViemModel 放置在控件 DataContext 中。
问题是:属性IntervalMinValue 未绑定到验证规则。如果我手动设置它 - 工作正常,但不是绑定。
问题是 Int32RangeChecker 对象附加到不属于可视化树的对象,因此无法访问视图模型。如果您查看输出 window,您将看到此错误...
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IntervalMinValue; DataItem=null; target element is 'Int32RangeChecker' (HashCode=32972388); target property is 'Minimum' (type 'Int32')
要解决此问题,您需要将 Minimum 属性 的绑定连接到可视化树的元素。一种方法是添加一个不可见的虚拟元素并绑定到它上面的数据上下文...
<FrameworkElement x:Name="dummyElement" Visibility="Hidden"/>
<TextBox>
<TextBox.Text>
<Binding Path="Interval" UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<local:TextBoxWithIntegerValidation>
<local:TextBoxWithIntegerValidation.ValidRange>
<local:Int32RangeChecker
Minimum="{Binding Source={x:Reference dummyElement}, Path=DataContext.IntervalMinValue}"
/>
</local:TextBoxWithIntegerValidation.ValidRange>
</local:TextBoxWithIntegerValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
我想根据标准规则验证文本框值,其中一对是最小值和最大值。问题是,我需要配置这个值(例如在设置文件中)。
我有验证规则:
public class TextBoxWithIntegerValidation : ValidationRule
{
private Int32RangeChecker _validRange;
public Int32RangeChecker ValidRange
{
get { return _validRange; }
set { _validRange = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var str = value as string;
if (str == null)
{
return new ValidationResult(false, Resources.TextResources.TextBoxIsEmpty_ErrorMessage);
}
int intValue = -1;
if (!int.TryParse(str, out intValue))
{
return new ValidationResult(false, Resources.TextResources.TextBoxNotIntegerValue_ErrorMessage);
}
if (intValue < ValidRange.Minimum)
{
return new ValidationResult(false,
string.Format(Resources.TextResources.TextBoxValueLowerThanMin_ErrorMessage, ValidRange.Minimum));
}
return new ValidationResult(true, null);
}
}
整数范围检查器:
public class Int32RangeChecker : DependencyObject
{
public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(0));
public int Maximum
{
get { return (int)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(100));
}
以及文本框验证:
<TextBox>
<TextBox.Text>
<Binding Path="Interval" UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<validationRules:TextBoxWithIntegerValidation>
<validationRules:TextBoxWithIntegerValidation.ValidRange>
<validationRules:Int32RangeChecker
Minimum="{Binding IntervalMinValue}"
/>
</validationRules:TextBoxWithIntegerValidation.ValidRange>
</validationRules:TextBoxWithIntegerValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
TextBox 放置在 UserControl 中,适当的 ViemModel 放置在控件 DataContext 中。
问题是:属性IntervalMinValue 未绑定到验证规则。如果我手动设置它 - 工作正常,但不是绑定。
问题是 Int32RangeChecker 对象附加到不属于可视化树的对象,因此无法访问视图模型。如果您查看输出 window,您将看到此错误...
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IntervalMinValue; DataItem=null; target element is 'Int32RangeChecker' (HashCode=32972388); target property is 'Minimum' (type 'Int32')
要解决此问题,您需要将 Minimum 属性 的绑定连接到可视化树的元素。一种方法是添加一个不可见的虚拟元素并绑定到它上面的数据上下文...
<FrameworkElement x:Name="dummyElement" Visibility="Hidden"/>
<TextBox>
<TextBox.Text>
<Binding Path="Interval" UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<local:TextBoxWithIntegerValidation>
<local:TextBoxWithIntegerValidation.ValidRange>
<local:Int32RangeChecker
Minimum="{Binding Source={x:Reference dummyElement}, Path=DataContext.IntervalMinValue}"
/>
</local:TextBoxWithIntegerValidation.ValidRange>
</local:TextBoxWithIntegerValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>