TemplateBinding 不适用于 ValidationRules 依赖属性 [英] TemplateBinding Not working on ValidationRules Dependency Property

查看:22
本文介绍了TemplateBinding 不适用于 ValidationRules 依赖属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作 cutom 验证器控件,但不知道为什么我想要绑定到模板化父级的 ValidationRules 上的 Message 属性.它可以运行,但每次都是空的.不知道为什么每次都是空的.

I am trying to make cutom validator controls but dont know why the Message Property that i have on the ValidationRules that i wanted to bind to the templated parent. It works runs but everytime its empty. Dont know why its empty everytime.

可以找到示例项目这里

风格

   <Style TargetType="{x:Type local:RequiredFieldBox}">
    <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:RequiredFieldBox}">
                <StackPanel Orientation="Vertical">

                    <TextBox>
                        <Binding  RelativeSource="{RelativeSource TemplatedParent}" Path="Text">
                        <Binding.ValidationRules>
                            <rule:RequiredFieldRule>
                                <rule:RequiredFieldRule.Params>
                                    <rule:ValidationParams 
                                        Message="{TemplateBinding Msg}"
                                        ValidationType="{TemplateBinding Type}"/>
                                </rule:RequiredFieldRule.Params>
                            </rule:RequiredFieldRule> 
                        </Binding.ValidationRules>
                    </Binding>
                        <TextBox.Style>
                    <Style TargetType="{x:Type TextBox}">
                      <Style.Triggers>
                           <Trigger Property="Validation.HasError" Value="true" >
                           <Setter Property="Foreground" Value="Red"/>
                           <Setter Property="Background" Value="MistyRose"/>
                           <Setter Property="BorderBrush" Value="Red"/>
                           <Setter Property="BorderThickness" Value="1.0"/>
                            <Setter Property="VerticalContentAlignment" Value="Center"/>
                           </Trigger>
                       </Style.Triggers>
                      <Setter Property="Validation.ErrorTemplate">
                         <Setter.Value>
                            <ControlTemplate>
                               <StackPanel>
                                  <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="40">
                                    <AdornedElementPlaceholder x:Name="Holder"/>
                                    <Image Height="{Binding Height, ElementName=Holder}" Width="20" Margin="10,0"
                                        Source="/Images/restricted.png" ToolTip="{Binding ElementName=Holder, 
                                        Path=AdornedElement.(Validation.Errors)
                     [0].ErrorContent}"/>
                                 </StackPanel>
                               </StackPanel>
                            </ControlTemplate>
                         </Setter.Value>
                    </Setter>
                 </Style>
             </TextBox.Style>
          </TextBox>
         </StackPanel>
        </ControlTemplate>
   </Setter.Value>
</Setter>

验证参数类

public class ValidationParams : DependencyObject
{

    public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(
      "Message",
      typeof(string),
      typeof(ValidationParams),
      new FrameworkPropertyMetadata(null));
    // Dependency Properties

    public static readonly DependencyProperty ValidationTypeProperty = DependencyProperty.Register("ValidationType",
                                                                                          typeof(RequiredFieldRule.EnmValidationType),
                                                                                          typeof(ValidationParams),
                                                                                          new FrameworkPropertyMetadata(RequiredFieldRule.EnmValidationType.FieldNotEmpty));
    public static readonly DependencyProperty FieldNameProperty = DependencyProperty.Register("FieldName",
                                                                                         typeof(string),
                                                                                         typeof(ValidationParams),
                                                                                         new FrameworkPropertyMetadata(string.Empty));
    public string FieldName
    {
        get { return (string)GetValue(FieldNameProperty); }
        set { SetValue(FieldNameProperty, value); }
    }
    // Properties
    public string Message
    {
        get { return (string)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }

    [Category("ValidationType")]
    public RequiredFieldRule.EnmValidationType ValidationType
    {
        get { return (RequiredFieldRule.EnmValidationType)GetValue(ValidationTypeProperty); }
        set { SetValue(ValidationTypeProperty, value); }

    }
}

自定义控件类

public class RequiredFieldBox : Control
{

    static RequiredFieldBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(RequiredFieldBox), new FrameworkPropertyMetadata(typeof(RequiredFieldBox)));
    }
    public static readonly DependencyProperty MsgProperty = DependencyProperty.Register(
     "Msg",
     typeof(string),
     typeof(RequiredFieldBox),
     new FrameworkPropertyMetadata(null)
   );
    public enum EnmValidationType
    {
        FieldNotEmpty,
        FieldNumeric,
        FieldIPAddress
    }
    public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type",
                                                                                         typeof(RequiredFieldBox.EnmValidationType),
                                                                                         typeof(RequiredFieldBox),
                                                                                         new FrameworkPropertyMetadata(RequiredFieldBox.EnmValidationType.FieldNotEmpty));
    public EnmValidationType Type
    {
        get { return (EnmValidationType) GetValue(TypeProperty); }
        set { SetValue(TypeProperty, value);}
    }
    private static void MessageChanaged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        RequiredFieldBox sh = (RequiredFieldBox)d;
        if (sh.Msg != (string)e.OldValue)
            sh.Msg = (string)e.NewValue;
    }
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
    "Text",                               //Property name
    typeof( object ),                           //Property type
    typeof( RequiredFieldBox ));

    public string Msg
    {
        get { return (string)GetValue(MsgProperty); }
        set { SetValue(MsgProperty, value); }
    }

    public object Text
    {
        get { return GetValue(TextProperty);}
        set { SetValue(TextProperty, value); }
    }
}

验证规则类

公共类 RequiredFieldRule : ValidationRule{

public class RequiredFieldRule : ValidationRule {

    public enum EnmValidationType
    {
        FieldNotEmpty,
        FieldNumeric,
        FieldIPAddress
    }

    // Local variables and objects
    private ValidationParams mParams = new ValidationParams();

    public ValidationParams Params
    {
        get { return mParams; }
        set { mParams = value;}
    }

    // Override
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        ValidationResult objResult = null;
        string sValue = value as string;
        objResult = new ValidationResult(true, null);
        switch (Params.ValidationType)
        {
            case EnmValidationType.FieldNotEmpty:
                if (string.IsNullOrEmpty(sValue) == true)
                    return new ValidationResult(false, Params.Message);
                break;
            case EnmValidationType.FieldNumeric:
                int iValue = 0;
                if (int.TryParse(sValue, out iValue) == false)
                    objResult = new ValidationResult(false, Params.Message);
                break;
            case EnmValidationType.FieldIPAddress:
                break;
        }
        return objResult;
    }

}

推荐答案

在验证规则中没有上下文或树连接,因为模板绑定大致等同于 RelativeSource 绑定它不会工作.你可能不走运...

In a validation rule there is no context or tree connection, as a template binding is roughly equivalent to a RelativeSource binding it will not work. You might be out of luck...

通常唯一有效的是Source 结合 StaticResourcex:Referencex:Static,因为您不能通过名称引用模板化父项,也许可以通过另一个控件隧道它,例如类似:

Usually the only thing that works is Source in combination with StaticResource, x:Reference or x:Static, as you cannot refer to the templated parent via name you maybe can tunnel it through another control, e.g. something like:

<TextBox x:Name="RequiredFieldBox"
         Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}">
    <TextBox.Resources>
        <rule:RequiredFieldRule x:Key="rule">
            <rule:RequiredFieldRule.Params>
                <rule:ValidationParams 
                    Message="{Binding Tag.Msg, Source={x:Reference RequiredFieldBox}}"
                    ValidationType="{Binding Tag.Type, Source={x:Reference RequiredFieldBox}}"/>
            </rule:RequiredFieldRule.Params>
        </rule:RequiredFieldRule>
    </TextBox.Resources>
    <!-- ... --->
         <Binding.ValidationRules>
             <StaticResource ResourceKey="rule"/>
         </Binding.ValidationRules>

(如果将 ValidationRule 留在原地,x:Reference 很可能会抱怨循环依赖)

(If the ValidationRule would be left in place the x:Reference in all likelihood would complain about cyclical dependency)

使用 StaticResource 和隧道元素的替代方法:

An alternative using StaticResource and a tunnel element:

<StackPanel Orientation="Vertical">
    <StackPanel.Resources>
        <FrameworkElement x:Key="Tunnel"
                Tag="{Binding RelativeSource={RelativeSource AncestorType=local:RequiredFieldBox}}" />
    </StackPanel.Resources>
    <StaticResource ResourceKey="Tunnel" />
    <TextBox x:Name="RequiredFieldBox">
        <TextBox.Text>
            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Text">
                <Binding.ValidationRules>
                    <rule:RequiredFieldRule>
                        <rule:RequiredFieldRule.Params>
                            <rule:ValidationParams
                                    Message="{Binding Tag.Msg, Source={StaticResource Tunnel}}"
                                    ValidationType="{Binding Tag.Type, Source={StaticResource Tunnel}}" />
                        </rule:RequiredFieldRule.Params>
                    </rule:RequiredFieldRule>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>

这篇关于TemplateBinding 不适用于 ValidationRules 依赖属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆