C# UserControl的WPF样式验证错误
我已经使用DataAnnotations和INotifyDataError在应用程序中实现了验证,并且可以成功地显示何时发生错误以及错误是什么。我希望将默认错误模板更改为输入值的文本框的样式 如果TextBox与创建底层数据模型绑定的用户控件位于同一个UserControl中,那么这对我来说是正确的 然而,我有很多输入,因此决定提取一个UserControl来封装标签和文本框。问题是,这样做后,我无法再获取文本框来指示错误,我将获取整个控件周围的默认红色框 我尝试了一些建议,比如让孩子控件实现INotifyDataError,但到目前为止我没有运气。这篇文章是同一个问题,我无法找到一个解决方案使用它,所以我希望与更多的标签,这可能会引起更多的注意和解决方案 这是我制作的一个小样本,显示了这个问题。如果输入了无效年龄,则顶部输入将文本框样式设置为红色,但底部用户控件的周围只是一个红色框C# UserControl的WPF样式验证错误,c#,wpf,validation,xaml,user-controls,C#,Wpf,Validation,Xaml,User Controls,我已经使用DataAnnotations和INotifyDataError在应用程序中实现了验证,并且可以成功地显示何时发生错误以及错误是什么。我希望将默认错误模板更改为输入值的文本框的样式 如果TextBox与创建底层数据模型绑定的用户控件位于同一个UserControl中,那么这对我来说是正确的 然而,我有很多输入,因此决定提取一个UserControl来封装标签和文本框。问题是,这样做后,我无法再获取文本框来指示错误,我将获取整个控件周围的默认红色框 我尝试了一些建议,比如让孩子控件实现I
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ValidatorTest" mc:Ignorable="d" x:Class="ValidatorTest.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<ResourceDictionary>
<CollectionViewSource x:Key="customerViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Customer}, CreateList=True}"/>
<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"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid DataContext="{StaticResource customerViewSource}">
<Grid x:Name="grid1" HorizontalAlignment="Left" Margin="19,27,0,0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label Content="Age:" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center"/>
<TextBox x:Name="ageTextBox" HorizontalAlignment="Left" Height="23" Margin="3"
Text="{Binding Age, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}"
VerticalAlignment="Center"
Width="120"
/>
</StackPanel>
<local:UnitInput Grid.Row="1"
Label="Age"
Value="{Binding Age, Mode=TwoWay, ValidatesOnExceptions=True}"/>
</Grid>
</Grid>
//
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
已加载私有无效窗口(对象发送器、路由目标)
{
CollectionViewSource customerViewSource=((CollectionViewSource)(this.FindResource(“customerViewSource”));
customerViewSource.Source=new[]{new Customer{
年龄=26}};
}
}
使用System.ComponentModel.DataAnnotations;
公共类客户:模型库
{
私人双倍年龄;
[射程(21,55)]
[必需(ErrorMessage=“年龄是必需的。”)]
公众双倍年龄
{
得到
{
返回这个年龄;
}
设置
{
this.ValidateProperty(()=>this.Age,value);
如果(!double.Equals(value,this.age))
{
年龄=价值;
this.raiseProperty已更改(()=>this.Age);
}
}
}
}
//
///UnitInput.xaml的交互逻辑
///
公共部分类UnitInput:UserControl
{
公共单位输入()
{
this.InitializeComponent();
}
公共字符串标签
{
得到
{
返回(字符串)GetValue(LabelProperty);
}
设置
{
SetValue(LabelProperty,value);
}
}
//使用DependencyProperty作为标签的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读DependencyProperty LabelProperty=
DependencyProperty.Register(“标签”)、typeof(字符串)、typeof(UnitInput)、new PropertyMetadata(“标签”);
公共字符串值
{
得到
{
返回(字符串)GetValue(ValueProperty);
}
设置
{
设置值(ValueProperty,value);
}
}
//使用DependencyProperty作为值的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性ValueProperty=
Register(“Value”、typeof(string)、typeof(UnitInput)、newpropertyMetadata(null));
}
提前感谢您的建议。我没有时间在新项目中设置您的所有代码,但我确实注意到了一个潜在的问题。尝试更改
单元输入
控件中的绑定
s:
<UserControl x:Class="ValidatorTest.UnitInput"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" >
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UnitInput}}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Label}" VerticalAlignment="Center" Width="100"/>
<TextBox Grid.Column="1" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Value, Mode=TwoWay}" HorizontalContentAlignment="Right" VerticalAlignment="Top" Width="80" Margin="5"/>
</Grid>
</UserControl>
区别在于这一行:
<Grid DataContext="{Binding RelativeSource={RelativeSource
AncestorType={x:Type UnitInput}}}">
要使用的正确的AncestorType
值是UserControl
(UnitInput
)的名称/类型,而不是标准的UserControl
,因为其中没有声明标签或值
属性。在VisualStudio的“输出”窗口中会出现一个类似于下面的错误,当您遇到数据绑定问题时,应该首先查看该窗口
System.Windows.Data错误:40:BindingExpression路径错误:在“对象”“用户控件”(HashCode=55649279)上找不到“标签”属性。BindingExpression:Path=Label
请注意,您可能还有更多错误。。。这只是我第一次看到。谢谢你的建议,但我没有收到这个错误,如果它不正确,那么我不相信我会看到它们所绑定的值,我确实看到了。话虽如此,我同意最好是明确的,所以我做出了改变。谢谢
<UserControl x:Class="ValidatorTest.UnitInput"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" >
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UnitInput}}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Label}" VerticalAlignment="Center" Width="100"/>
<TextBox Grid.Column="1" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding Value, Mode=TwoWay}" HorizontalContentAlignment="Right" VerticalAlignment="Top" Width="80" Margin="5"/>
</Grid>
</UserControl>
<Grid DataContext="{Binding RelativeSource={RelativeSource
AncestorType={x:Type UnitInput}}}">