WPF数据验证绑定失败
本文关键字:失败 绑定 验证 数据 WPF | 更新日期: 2023-09-27 17:50:58
我试图从我的控件样式绑定到控件中定义的属性。该控件继承自TextBox,名为changetextboxwiththrangeunits。我试图从我创建的ValidationRule类绑定到它们。这里是Setter用于验证文本
<Setter Property="Text">
<Setter.Value>
<Binding RelativeSource="{RelativeSource Self}"
Path="Text"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<basic:DoubleValidationRule>
<basic:DoubleValidationRule.MinMaxDependencyObject>
<basic:MinMaxDependencyObject Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MinimumValue}"
Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MaximumValue}" />
</basic:DoubleValidationRule.MinMaxDependencyObject>
</basic:DoubleValidationRule>
</Binding.ValidationRules>
</Binding>
</Setter.Value>
</Setter>
我不明白为什么它说不能找到源绑定。下面是错误:
System.Windows。数据错误:4:无法找到绑定引用的源'RelativeSource FindAncestor, AncestorType='Frasca.Simplicity.Controls.UnitControls。ChangeTextBoxWithRangeUnits",AncestorLevel ="1"。BindingExpression:路径= MinimumValue;DataItem =零;目标元素是'MinMaxDependencyObject' (HashCode=16320155);目标属性为"Minimum"(类型为"Double")
EDIT Complete XAML
<Style x:Key="ChangeTextBoxWithRangeUnits"
TargetType="{x:Type local:ChangeTextBoxWithRangeUnits}"
BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Validation.ErrorTemplate"
Value="{x:Null}" />
<Setter Property="Height"
Value="64" />
<Setter Property="FontSize"
Value="22" />
<Setter Property="Margin"
Value="5" />
<Setter Property="Background"
Value="LightGray" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="KeyboardNavigation.TabNavigation"
Value="None" />
<Setter Property="AllowDrop"
Value="true" />
<Setter Property="ScrollViewer.PanningMode"
Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled"
Value="False" />
<Setter Property="Text">
<Setter.Value>
<Binding RelativeSource="{RelativeSource Self}"
Path="Text"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<basic:DoubleValidationRule>
<basic:DoubleValidationRule.MinMaxDependencyObject>
<basic:MinMaxDependencyObject Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MinimumValue}"
Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithRangeUnits}}, Path=MaximumValue}" />
</basic:DoubleValidationRule.MinMaxDependencyObject>
</basic:DoubleValidationRule>
</Binding.ValidationRules>
</Binding>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ChangeTextBoxWithUnits}">
<Grid>
<Border Name="bg"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Width="{TemplateBinding Width}"
CornerRadius="15"
SnapsToDevicePixels="true">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Name="mValueStackPanel"
VerticalAlignment="Bottom"
HorizontalAlignment="Center">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBox Name="PART_UnitTextBlock"
Style="{DynamicResource InlineTextBox}"
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=Units}"
FontSize="14"
Margin="3,0,0,0"
Foreground="{TemplateBinding Foreground}" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Grid.Row="2"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=Label}"
FontSize="14"
Foreground="{TemplateBinding Foreground}" />
</StackPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ChangeTextBoxWithUnits}}, Path=DisabledText}"
Foreground="{TemplateBinding Foreground}"
Grid.Row="0"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Visibility="Collapsed"
x:Name="mDisabledTextBlock" />
<!-- Horizontal line -->
<Rectangle Height="1"
Margin="10,0"
Grid.Row="1"
Opacity="0.15"
SnapsToDevicePixels="True"
Fill="{TemplateBinding Foreground}" />
<!-- Object which flashes when the textbox is selected -->
<Border Grid.RowSpan="3"
Background="White"
Name="FlashObject"
CornerRadius="15"
Opacity="0">
<Border.Effect>
<BlurEffect Radius="20" />
</Border.Effect>
</Border>
<!-- Object which flashes when the textbox has a validation error-->
<Border Grid.RowSpan="3"
Grid.ColumnSpan="2"
Background="Red"
Name="ErrorFlashObject"
CornerRadius="15"
Opacity="0">
<Border.Effect>
<BlurEffect Radius="20" />
</Border.Effect>
</Border>
</Grid>
</Border>
<!-- Object which glows when the user makes a change to the text value. -->
<Border Width="{Binding ElementName=bg, Path=ActualWidth}"
Height="{Binding ElementName=bg, Path=ActualHeight}"
CornerRadius="15"
Background="#FFF066"
Name="ChangeGlowObject"
Panel.ZIndex="-1"
Visibility="Collapsed">
<Border.Effect>
<BlurEffect Radius="20" />
</Border.Effect>
</Border>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasChangedValue"
Value="True" />
<Condition Property="IsEnabled"
Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="ChangeGlowObject"
Value="Visible" />
</MultiTrigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Background"
Value="#686868" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsEnabled"
Value="False" />
<!--<Condition Property="ShowTextWhenDisabled"
Value="False" />-->
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="mDisabledTextBlock"
Value="Visible" />
<Setter Property="Visibility"
TargetName="mValueStackPanel"
Value="Collapsed" />
</MultiTrigger>
<!-- trigger to flash the object when the textbox has an error -->
<Trigger Property="Validation.HasError"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation BeginTime="00:00:00"
Duration="00:00:00.2"
From="0"
To="1"
Storyboard.TargetName="ErrorFlashObject"
Storyboard.TargetProperty="Opacity">
<DoubleAnimation.EasingFunction>
<PowerEase Power="2"
EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="00:00:00.2"
Duration="00:00:00.5"
From="1"
To="0"
Storyboard.TargetName="ErrorFlashObject"
Storyboard.TargetProperty="Opacity">
<DoubleAnimation.EasingFunction>
<PowerEase Power="2"
EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<!-- trigger to flash the object when the textbox is selected -->
<EventTrigger RoutedEvent="FocusManager.GotFocus">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation BeginTime="00:00:00"
Duration="00:00:00.2"
From="0"
To="1"
Storyboard.TargetName="FlashObject"
Storyboard.TargetProperty="Opacity">
<DoubleAnimation.EasingFunction>
<PowerEase Power="2"
EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="00:00:00.2"
Duration="00:00:00.5"
From="1"
To="0"
Storyboard.TargetName="FlashObject"
Storyboard.TargetProperty="Opacity">
<DoubleAnimation.EasingFunction>
<PowerEase Power="2"
EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
RelativeSource
绑定不会沿着XML上行,它们沿着可视化树上行。这意味着当你要绑定的元素在该树内时,你只能使用它。
在这种情况下,您的DoubleValidationRule
是而不是一个UIElement,并且它在可视化树中是而不是,因此该规则上的RelativeSouce
绑定将失败。
不幸的是,在不知道DoubleValidationRule.MinMaxDependencyObject
的实现或目的的情况下,很难说你应该做什么。您可以通过更改验证规则的实现来绕过这个限制。
一种有效的方法是,您可以通过其x:Name
值
Minimum="{Binding MinimumValue, ElementName=TheMinimumTarget}
但这可能意味着你不能使用Style
来做到这一点,因为每个使用将(可能)绑定到表单上不同的元素。
看着你的编辑…窟?您将控件的文本绑定到控件的文本以附加验证规则?这是……我甚至不知道。
我建议将控件子类化,以便添加验证逻辑(例如,覆盖Text依赖属性的属性元数据),然后将您的模板应用于此新类型