gpt4 book ai didi

wpf - MVVM 中的 UI 绑定(bind)验证

转载 作者:行者123 更新时间:2023-12-03 10:14:13 27 4
gpt4 key购买 nike

我正在使用 DataTemplate 将一些代码转换为更合适的 MVVM 实现。 s 并且在某些类型的 UI 验证方面遇到问题。

我在 View 模型中的验证没有问题 -- IDataErrorInfo已实现,一切都很好。我遇到的问题是 UI 绑定(bind)错误,它们可能会将字母放入 TextBox。绑定(bind)到一个 int。

以前,我用过:

System.Windows.Controls.Validation.AddErrorHandler(userControl, handler) 

...并保留添加和删除的错误计数,以了解所有表单的数据是否正常。

但是现在我正在做 MVVM,我无权访问 userControl 来设置这个处理程序。所以我真的没有一个钩子(Hook)来开始这个。

有没有某种全局性的 DataTemplateApplied可用的事件处理程序,我可以在其中执行以下操作:
void OnDataTemplateApplied(object data, Control template)
{
if (data is MyViewModelBase)
{
Validation.AddErrorHandler(template, handler);
}
}

或者,也许我可以调用 AddErrorHandler一次在外部 Shell 窗口的 Bootstrap 中,然后每次触发事件时以某种方式确定哪个 ViewModel 正在为该特定控件提供动力?

我知道有些人喜欢制作所有 VM 字段字符串并在 VM 中进行大量类型转换——由于各种原因,这对于我们的系统来说是不现实的。

最佳答案

您可能对此答案感兴趣:https://stackoverflow.com/a/13335971/1094526
主要思想正是您所说的(订阅错误处理程序)。据我了解,问题是您无法从 ViewModel 访问控件,但这并不难解决

在我正在工作的项目中,我从 ViewModel 中公开了两个方法:AddUIError 和 RemoveUIError。我在 View 中创建了一个事件处理程序,并将 DataContext 转换为 ViewModel 的类型,并根据发生的情况调用 AddUIError 或 RemoveUIError。
我正在使用 DataTemplates 将 View 与 ViewModel 相关联,因此在应用模板时,DataContext 会自动设置为 ViewModel。如果需要,您可以将 ViewModel 存储在私有(private)字段中(在 View 中)并在每次 DataContext 更改时更新引用(有一个 DataContextChanged 事件)

如果这将在多个 ViewModel 中完成,您可以将这两个方法(AddUIError 和 RemoveUIError)放在 ViewModelBase 之类的类中,并将 ValidationError 事件处理移动到一个 Behavior 并在每个 View 中使用它。

有关行为部分的更多信息:
Behavior 类是 Expression Blend SDK 的一部分,因此如果您想遵循这种方式,您将需要它。

例如,行为对于将一些通用功能附加到许多组件而无需创建派生类很有用。

首先,我们需要在一个名为 ViewModelBase 的类中定义 AddUIError 和 RemoveUIError(当然,它是所有其他 ViewModel 的基类):

class ViewModelBase {
public void AddUIError(...) {/* Details ommitted */ }
public void RemoveUIError(...) {/* Details ommitted */ }
}

然后,通过子类化 Behavior 创建一个 Behavior。我们使用 FrameworkElement 作为模板参数,因此可以将此行为附加到任何 FrameworkElement(或派生类)实例:
class NotifyDataErrorsBehavior : Behavior<FrameworkElement>
{
// Called when the the Behavior is attached
protected override void OnAttached()
{
base.OnAttached();
// Initialize the handler for the Validation Error Event
_handler = new RoutedEventHandler(OnValidationRaised);
// Add the handler to the event from the element which is attaching this behavior
AssociatedObject.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _handler);
}

protected override void OnDetaching()
{
base.OnDetaching();
// Remove the event handler from the associated object
AssociatedObject.RemoveHandler(System.Windows.Controls.Validation.ErrorEvent, _handler);
}

private RoutedEventHandler _handler = null;


private void OnValidationRaised(object sender, RoutedEventArgs e)
{
var args = (System.Windows.Controls.ValidationErrorEventArgs)e;

ViewModelBase viewModel = AssociatedObject.DataContext as ViewModelBase;
if (viewModel != null)
{
// You can add only Exception validation errors if you want..

if (args.Action == ValidationErrorEventAction.Added)
viewModel.AddUIValidationError(...);
else if (args.Action == ValidationErrorEventAction.Removed)
viewModel.RemoveUIValidationError(...);
else
throw new NotSupportedException("ValidationErrorEventAction has changed");
}
}
}

最后在 XAML 中使用它:
1. 添加对 NotifyDataErrorsBehavior 所在命名空间的引用,以及对 System.Windows.Interactivity 命名空间的引用(来自 Expression Blend SDK):
<UserControl 
...
xmlns:behavior="clr-namespace:MyApp.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
>

2. 添加行为(与您的 UserControl 的内容处于同一级别:
<i:Interaction.Behaviors>
<behavior:NotifyDataErrorsBehavior/>
</i:Interaction.Behaviors>

前任:
<UserControl 
...
xmlns:behavior="clr-namespace:MyApp.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
>
<i:Interaction.Behaviors>
<behavior:NotifyDataErrorsBehavior/>
</i:Interaction.Behaviors>
<Grid>
...
</Grid>
</UserControl>

关于wpf - MVVM 中的 UI 绑定(bind)验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13596596/

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