WPF:绑定到验证规则的DependencyProperty

时间:2017-08-28 13:22:02

标签: c# wpf data-binding dependency-properties

我想根据标准规则验证文本框值,其中几个是Min和Max值。问题是,我需要配置这些值(例如在设置文件中)。

我有验证规则:

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);
        }
    }

Int范围检查器:

 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未绑定到验证规则。如果我手动设置 - 工作正常,但没有绑定。

1 个答案:

答案 0 :(得分:3)

问题是Int32RangeChecker对象附加到不属于可视树的对象,因此无法访问视图模型。如果查看输出窗口,您将看到此错误...

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>