设置 UserControl 的特定 child 的错误模板
Set error template of a specific child of a UserControl
我正在尝试了解如何将错误模板添加到 UserControl
的 child,并且我看到了其他类似的问题,但我仍然无法解决这个问题。
我的目标是创建一个 UserControl
,其中包含一个 TextBox
和一个 Label
,以及一个可选的只读 TextBox
。我已经实现了很多功能并且一切正常,除了整个 UserControl
在验证错误的情况下会出现红色边框。
我尝试将 Validation.ValidationAdornerSite
添加到 UserControl
的根元素,但没有成功。
此外,想法是验证应该在模型 类 内部完成,所以我不想在 UserControl
.
内部放置任何验证机制
在这种情况下,我不太了解绑定系统的工作原理。整个 UserControl
在错误上突出显示是有道理的,因为它是 UserControl
的 属性 绑定到 Model
的 属性,但我希望能够将错误“重定向”到带有 Validation.ValidationAdornerSite
的 child。我错过了什么或误解了什么?例如,如何突出显示 TextBox
"txt1"?
提前致谢!
这是我能想到的最小示例:
MyControl.xaml
<UserControl x:Class="MyNamespace.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel x:Name="ctRoot">
<Label x:Name="lbTitle" Content="MyLabel"/>
<TextBox x:Name="txt1" Text="{Binding Text}"/>
<TextBox x:Name="txt2"/>
</StackPanel>
</UserControl>
MyControl.xaml.cs
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
ctRoot.DataContext = this;
}
public static readonly DependencyProperty TextProperty = DependencyProperty
.Register("Text", typeof(string), typeof(MyControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
Model.cs
public class Model : INotifyDataErrorInfo, INotifyPropertyChanged
{
private string m_prop;
public string MyProp
{
get => m_prop;
set
{
m_errors.Clear();
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(MyProp)));
if (value.Length == 0)
{
m_errors.Add("Cannot be empty");
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(MyProp)));
}
m_prop = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProp)));
}
}
private List<string> m_errors = new List<string>();
public bool HasErrors => m_errors.Count > 0;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerable GetErrors(string propertyName)
{
return m_errors;
}
}
MyWindow.xaml
<Window x:Class="MyNamespace.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Title="MyWindow" Width="200" Height="200">
<StackPanel>
<local:MyControl Text="{Binding MyProp}" Margin="10"/>
</StackPanel>
</Window>
MyWindow.xaml.cs
public partial class MyWindow : Window
{
public Model model = new Model();
public MyWindow()
{
InitializeComponent();
DataContext = model;
}
}
您可以使用 Validation.ValidationAdornerSiteFor
更改显示哪个元素以指示发生错误。
<UserControl x:Class="WpfApp1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myControl">
<StackPanel x:Name="ctRoot">
<Label x:Name="lbTitle" Content="MyLabel"/>
<TextBox x:Name="txt1" Text="{Binding Text, ElementName=myControl}"
Validation.ValidationAdornerSiteFor="{Binding ElementName=myControl}"/>
<TextBox x:Name="txt2"/>
</StackPanel>
</UserControl>
我正在尝试了解如何将错误模板添加到 UserControl
的 child,并且我看到了其他类似的问题,但我仍然无法解决这个问题。
我的目标是创建一个 UserControl
,其中包含一个 TextBox
和一个 Label
,以及一个可选的只读 TextBox
。我已经实现了很多功能并且一切正常,除了整个 UserControl
在验证错误的情况下会出现红色边框。
我尝试将 Validation.ValidationAdornerSite
添加到 UserControl
的根元素,但没有成功。
此外,想法是验证应该在模型 类 内部完成,所以我不想在 UserControl
.
在这种情况下,我不太了解绑定系统的工作原理。整个 UserControl
在错误上突出显示是有道理的,因为它是 UserControl
的 属性 绑定到 Model
的 属性,但我希望能够将错误“重定向”到带有 Validation.ValidationAdornerSite
的 child。我错过了什么或误解了什么?例如,如何突出显示 TextBox
"txt1"?
提前致谢!
这是我能想到的最小示例:
MyControl.xaml
<UserControl x:Class="MyNamespace.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel x:Name="ctRoot">
<Label x:Name="lbTitle" Content="MyLabel"/>
<TextBox x:Name="txt1" Text="{Binding Text}"/>
<TextBox x:Name="txt2"/>
</StackPanel>
</UserControl>
MyControl.xaml.cs
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
ctRoot.DataContext = this;
}
public static readonly DependencyProperty TextProperty = DependencyProperty
.Register("Text", typeof(string), typeof(MyControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
Model.cs
public class Model : INotifyDataErrorInfo, INotifyPropertyChanged
{
private string m_prop;
public string MyProp
{
get => m_prop;
set
{
m_errors.Clear();
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(MyProp)));
if (value.Length == 0)
{
m_errors.Add("Cannot be empty");
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(MyProp)));
}
m_prop = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProp)));
}
}
private List<string> m_errors = new List<string>();
public bool HasErrors => m_errors.Count > 0;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerable GetErrors(string propertyName)
{
return m_errors;
}
}
MyWindow.xaml
<Window x:Class="MyNamespace.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Title="MyWindow" Width="200" Height="200">
<StackPanel>
<local:MyControl Text="{Binding MyProp}" Margin="10"/>
</StackPanel>
</Window>
MyWindow.xaml.cs
public partial class MyWindow : Window
{
public Model model = new Model();
public MyWindow()
{
InitializeComponent();
DataContext = model;
}
}
您可以使用 Validation.ValidationAdornerSiteFor
更改显示哪个元素以指示发生错误。
<UserControl x:Class="WpfApp1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myControl">
<StackPanel x:Name="ctRoot">
<Label x:Name="lbTitle" Content="MyLabel"/>
<TextBox x:Name="txt1" Text="{Binding Text, ElementName=myControl}"
Validation.ValidationAdornerSiteFor="{Binding ElementName=myControl}"/>
<TextBox x:Name="txt2"/>
</StackPanel>
</UserControl>