在WPF中的UserControl中展示控件的验证错误模板

13
如何让 WPF 错误模板在 WPF 中的 UserControl 中的控件上显示?
我有一个包含两个标签、两个文本框和一个复选框的 UserControl。其中一个文本框表示实体的名称,并绑定到由我的 ViewModel 公开的 Model 属性下的 Name 属性,该 ViewModel 是我的 Window 的 DataContext。
Model 类实现了 IDataErrorInfo 接口,并通过单元测试确认当名称为空时,属性索引器实现会返回一个错误。我已经将其绑定到 UserControl 中支持 Name TextBox 的依赖属性。当遇到验证错误时,WPF 错误模板会将红色边框放置在整个 UserControl 而不仅是 Name TextBox 上。
UserControl 对名称字段的绑定如下所示。
<vc:MyUserControl ItemName="{Binding Model.Name, ValidatesOnDataErrors=True}" />

我自定义用户控件和支持的依赖属性的简化版本如下。

<UserControl>
    <Grid>
       <TextBox Text="{Binding ItemName}" />
    </Grid>
</UserControl>

public partial class MyUserControl: UserControl
{
    public static readonly DependencyProperty ItemNameProperty = 
        DependencyProperty.Register(
            "ItemName", 
            typeof(string), 
            typeof(MyUserControl), 
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
    );

    public string ItemName
    {
        get { return (string)GetValue(ItemNameProperty); }
        set { SetValue(ItemNameProperty, value); }
    }
}

到目前为止,我找到的与此问题相关的信息都是关于Silverlight或使用转换器来不显示红色边框的(这对我来说没有意义)。这些信息都是在stackoverflow上找到的。

有人能够解决这个WPF问题吗?我是否忽视了一些显而易见的东西?


相关问题请参见这里这里 - LPL
谢谢,LPL。在研究这个问题时,我已经看到了这两个问题。第二个链接上的被接受的答案是我在问题中提到的转换器的使用。对我来说,这似乎是错误的。第一个问题中被接受的答案也对我没有起作用。 - CoderDawson
1个回答

12
UserControlErrorTemplate 将在绑定到你的 UserControl 使用 ValidatesOnDataErrors=True 时使用。但是,你可以通过使用 Validation.ErrorTemplate Attached Property 来移除红色边框。
在实现支持依赖属性的后备数据的 IDataErrorInfo 时,UserControl 中的所有控件仅在验证其绑定时显示红色边框。
public class MyUserControl : UserControl, IDataErrorInfo
{
   public static readonly DependencyProperty ItemNameProperty =
       DependencyProperty.Register(
           "ItemName",
           typeof(string),
           typeof(MyUserControl),
           new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
   );

   public string ItemName
   {
      get { return (string)GetValue(ItemNameProperty); }
      set { SetValue(ItemNameProperty, value); }
   }

   public string Error
   {
      get { throw new NotImplementedException(); }
   }

   public string this[string columnName]
   {
      get
      {
         // use a specific validation or ask for UserControl Validation Error 
         return Validation.GetHasError(this) ? "UserControl has Error" : null;
      }
   }
}

这里是简化后的XAML

<UserControl Validation.ErrorTemplate="{x:Null}">
   <Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
      <TextBox Text="{Binding ItemName, ValidatesOnDataErrors=True}" />
   </Grid>
</UserControl>

加法

如果您想区分错误,可以获取 DependencyProperty 的 BindingExpression 并检查 HasError 属性

BindingExpression be = BindingOperations.GetBindingExpression(this, ItemNameProperty);
return be != null && be.HasError ? "ItemName has Error" : null;

再次感谢LPL。我最初尝试了类似的更改,但是我无法确定UserControl内部的哪个TextBox存在错误,因为在TextBox本身上调用Validation.GetHasError总是返回false。由于我的UserControl中有两个TextBox,有没有办法确定哪个框实际上存在错误? - CoderDawson
不确定我之前做错了什么,但这对我来说似乎有效。我仍然不知道如何区分唯一文本框上的错误,但在这一点上,我只会在其中一个上进行验证。谢谢,LPL! - CoderDawson
1
我已经添加了一个建议来区分错误。 ;) - LPL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接