C# TemplateBinding不处理ValidationRules依赖项属性
我正在尝试创建cutom验证器控件,但不知道为什么ValidationRules上的Message属性要绑定到模板化父级。它可以运行,但每次都是空的。不知道为什么每次都是空的 可以找到示例项目 风格C# TemplateBinding不处理ValidationRules依赖项属性,c#,wpf,xaml,C#,Wpf,Xaml,我正在尝试创建cutom验证器控件,但不知道为什么ValidationRules上的Message属性要绑定到模板化父级。它可以运行,但每次都是空的。不知道为什么每次都是空的 可以找到示例项目 风格 <Style TargetType="{x:Type local:RequiredFieldBox}"> <Setter Property="Template"> <Setter.Value> <ControlTe
<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 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); }
}
}
验证规则类
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
{
在验证规则中,没有上下文或树连接,因为模板绑定大致相当于
相对资源
绑定,它将不起作用。您可能运气不好
通常,唯一有效的方法是与StaticResource
或x: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>
只是想一想为什么ValidationType可以工作?而消息只是不工作,这个绑定会引发一个异常。不知道为什么,但无法创建Tag.Type依赖项Property@NividDholakia:
ValidationType
使用了TemplateBinding
?这很有趣,您可能想查看任何输出,也许吧模板绑定确实可以工作,但还有一些问题。我发布的代码中没有绑定错误。所有内容都是正确的。如果您需要,可以从添加的链接下载示例项目的副本。很抱歉,该链接现在是最新的WpfCustomValidatorProject@NividDholakia:ValidationType目前也不工作正如我所看到的,它总是默认值…我添加了另一个方法来隧道所需的属性。
<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>
<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>