【问题标题】:Set error template of a specific child of a UserControl设置 UserControl 的特定子项的错误模板
【发布时间】:2022-01-13 00:42:08
【问题描述】:

我正在尝试了解如何将错误模板添加到 UserControl 的子代,并且我看到了其他类似的问题,但我仍然无法解决这个问题。

我的目标是创建一个具有TextBoxLabelUserControl,以及可选的只读TextBox。我已经实现了很多功能并且一切正常,除了整个UserControl 会在验证错误的情况下出现红色边框。

我尝试将Validation.ValidationAdornerSite 添加到UserControl 的根元素,但没有成功。

另外,这个想法是验证应该在模型类中完成,所以我不想在UserControl 中放置任何验证机制。

在这种情况下,我真的不明白绑定系统是如何工作的。整个UserControl 在错误中突出显示是有道理的,因为它是绑定到Model 属性的UserControl 属性,但我希望能够将错误“重定向”到Validation.ValidationAdornerSite 的孩子。我错过了什么或误解了什么?例如,如何突出显示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;
    }
}

【问题讨论】:

    标签: c# wpf xaml data-binding


    【解决方案1】:

    您可以使用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 上使用Validation.ValidationAdornerSite 不起作用吗?因为文档的备注部分说“Validation.ValidationAdornerSite 和 Validation.ValidationAdornerSiteFor 附加属性相互引用,您可以设置任何一个。”。
    • @RodolfoRibeiro 因为这将无法解决后代的名称并导致绑定错误。
    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 2018-02-07
    • 2016-12-22
    相关资源
    最近更新 更多