gpt4 book ai didi

c# - 带有 MVVM 和 DataAnnotations 的 WPF,UserControl 中的验证错误

转载 作者:太空狗 更新时间:2023-10-29 22:01:05 24 4
gpt4 key购买 nike

我有一个 UserControl,它将在我们开发的整个应用程序中重复使用。我们正在使用基于 MVVMLight 的框架。

为简单起见,假设用户控件仅包含一个文本框并公开一个名为“Quantity”的依赖属性。用户控件上的文本框数据绑定(bind)到依赖属性“数量”。

当在 View 上使用用户控件时,用户控件的“数量”依赖属性数据绑定(bind)到 ViewModel 中的属性。 (这个 ViewModel 是我们通过 MVVMLight ViewModelLocator 的 View 的数据上下文)。

这一切都很好!绑定(bind)有效,属性设置如我所料。在验证之前一切都很好。

我们正在使用 DataAnnotations 来装饰我们的 ViewModel 属性。 ViewModel 包含 INotifyDataErrorInfo 的自定义实现。我们为大多数输入控件实现了自定义样式,以在控件周围显示红色边框,并在控件旁边显示一条消息,显示验证错误消息。所有这些在正常情况下都很好用(例如, View 上的文本框绑定(bind)到 View 模型中的属性)。

当我使用此用户控件尝试相同的方法时,我最终得到的是整个用户控件周围的红色边框,并且实际文本框上没有错误指示。似乎 UI 中反射(reflect)了错误这一事实,但它只是没有进入我想要的控件。

我在 stackoverflow 上搜索了这个问题,在这些问题和解决方案中,似乎没有一个适合我的情况。

我的第一个猜测是,因为实际的文本框直接绑定(bind)到依赖属性本身,而不是我的 View 模型上的属性,所以它没有被正确地通知生成的错误。有什么方法可以通过用户控件将 View 模型中生成的错误传播到文本框吗?

如果您能提供任何帮助或建议,我们将不胜感激。

这是 UserControl xaml。

<UserControl x:Class="SampleProject.UserControls.SampleControl"
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" x:Name="sampleControl"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=sampleControl}">
<TextBox Text="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Width="100" Height="30" />
</Grid>
</UserControl>

背后的UserControl代码。

public partial class SampleControl : UserControl
{
public SampleControl()
{
InitializeComponent();
}

public static readonly DependencyProperty QuantityProperty =
DependencyProperty.Register("Quantity", typeof(int?), typeof(SampleControl),
new FrameworkPropertyMetadata{DefaultValue=null, BindsTwoWayByDefault = true});

public int? Quantity
{
get { return (int?)GetValue(QuantityProperty); }
set { SetValue(QuantityProperty, value); }
}
}

用于 View 。

<userControls:SampleControl Grid.Row="1" Quantity="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Height="60" Width="300"/>

ViewModel 属性。

[Required(ErrorMessage = "Is Required")]
[Range(5, 10, ErrorMessage = "Must be greater than 5")]
public int? Quantity
{
get { return _quantity; }
set { Set(() => Quantity, ref _quantity, value); }
}
private int? _quantity;

(*注意,setter 中的 Set 方法只是基本 View 模型中的辅助方法,用于设置支持属性并为其引发 PropertyChanged 事件。)

最佳答案

尝试从 UserControl 中删除 DataContext。不是设置它,而是使用 RelativeSource Binding 直接从 TextBox Bind 到实际属性:

<TextBox Text="{Binding Quantity, RelativeSource={RelativeSource Mode=FindAncestor, 
AncestorType={x:Type YourControlNamespace:SampleControl,
ValidatesOnDataErrors=True}}}" Width="100" Height="30" />

更新>>>

否则,只要绑定(bind)到此属性的 View 模型总是具有要绑定(bind)到的同名属性,您就可以获得此Binding像这样搜索 parent 的 DataContext:

<TextBox Text="{Binding Quantity, RelativeSource={RelativeSource Mode=FindAncestor, 
AncestorLevel=2, ValidatesOnDataErrors=True}}}" Width="100" Height="30" />

您需要将 2 更改为 TextBox 在到达具有正确属性访问权限的控件之前具有的正确数量的父元素。例如,使用级别 2 意味着框架将尝试在 DataContext 中找到名为 Quantity 的属性以Bind TextBox 父级的父控件的 使用 AncestorLevel 时比较棘手,但我相信像 Grid 这样的“隐藏”元素不包括在父级中。

关于c# - 带有 MVVM 和 DataAnnotations 的 WPF,UserControl 中的验证错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19215762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com