簡體   English   中英

TemplateBinding無法在ValidationRules依賴項屬性上使用

[英]TemplateBinding Not working on ValidationRules Dependency Property

我正在嘗試制作cutom驗證程序控件,但不知道為什么我要綁定到模板化父項的ValidationRules上的Message屬性。 它可以運行,但每次都為空。 不知道為什么它每次都是空的。

示例項目可以在這里找到

樣式

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

    }
}

CustomControl類

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 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綁定大致等效,因此它將不起作用。 你可能不走運...

通常唯一有效的方法是將SourceStaticResourcex:Referencex:Static結合使用,因為您無法通過名稱引用模板化父級,因此您可以將其通過另一個控件進行隧道傳輸,例如:

<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很可能會抱怨周期性依賴性)


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

<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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM