![](/img/trans.png)
[英]TemplateBinding in Storyboard | ObjectAnimationUsingKeyFrames not working
[英]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
綁定大致等效,因此它將不起作用。 你可能不走運...
通常唯一有效的方法是將Source
與StaticResource
, x:Reference
或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>
(如果將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.