如何禁止验证错误时自动数据绑定
本文关键字:错误 数据绑定 验证 何禁止 禁止 | 更新日期: 2023-09-27 18:34:12
我正在使用 MVVM 作为中继命令和数据绑定在 C# WPF 中创建一个简单的数据库应用程序。对于数据库内容的内存存储,我使用 ObservableCollection
,它绑定到 Datagrid,如下所示:
<DataGrid ItemsSource="{Binding Path=Softwares, Mode=OneWay}" SelectedItem="{Binding Path=SoftwareSelection, Mode=TwoWay}">
项目后,用户可以选择对其进行编辑。对于编辑,将打开一个表单,其中包含一堆文本框,其中包含给定实体的数据。所有字段都使用 IDataErrorInfo
进行验证,除非所有文本框都有效,否则不会启用 ok 按钮,因此无法将任何更改保存到集合和数据库中。
下面是示例文本框的外观:
<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
但是棘手的部分是,如果我更改文本框中的某些值然后关闭窗口,新值将传播到ObservableCollection
,这是我不想这样做的。您有任何想法,如何防止此类行为吗?我希望仅在单击按钮后才能进行数据绑定工作。否则,databindng 运行良好,因此按钮 (dis/en( 在单击后启用并反映对数据库和集合的更改。两个视图由不同的视图模型提供服务,视图之间的数据通过触发事件传递。
我试图将DataGrid
UpdateSourceTrigger=Explicit
添加到 ItemsSource 绑定中,但没有帮助。也许,我缺少一些应用程序逻辑?
非常感谢您的帮助。
这是大多数 WPF 开发人员犯假设错误的地方!
在 MVVM 中,脏数据可以存储在ViewModel
中,这就是 VM 层的用途!它从Model
的角度模仿了View
,因为View
是错误的,所以ViewModel
也会在错误中。这是完全有效的。
所以话虽如此,问题仍然存在
您将如何不允许临时/脏数据流向您 可观察集合?
两种方式...
-
如果你的
ObservableCollection
特定于你的模型类(比如MyItem
(,那么如果你的模型类(MyItem
(是一个实体类''DAL类''NHibernate类,创建一个名为ViewModelMyItem
的类MyItem
包装器,然后而不是使用ObservableCollection<ViewModelMyItem>
而不是ObservableCollection<MyItem>
。这样,来自
View
的脏数据就会在ViewModelMyItem
内部,并且只有在单击Save
按钮时才能合法地飞回模型类(MyItem
(。这意味着在Save Command
的Execute()
委托中,您可以将ViewModelMyItem
的属性复制''克隆到Item
的属性中,如果ViewModelMyItem
中的验证正常的话。因此,如果
Item
是EntityType
类/NHibernate
类/WCF
客户端模型类,则它始终只有有效数据,因为ViewModelMyItem
正在预先过滤临时/脏信息。 -
可以使用
Explicit
绑定模型。它会停止TwoWay
数据流回 sorceItem
,除非显式调用BindingExpressions.UpdateSource()
。但据我说,这直接击败了 MVVM,因为
ViewModel
不会有 UI 显示的内容!但是,您仍然可以使用*附加行为*通过保留在MVVM空间中来管理显式绑定!
让我知道这是否有帮助!
最好将代码放入域对象的属性库。然后通过触发NotifyPropertyChanged
处理程序与视觉对象同步。
有关此主题的更多信息:
http://msdn.microsoft.com/en-us/library/ms743695.aspxhttp://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
将绑定模式设置为显式应该需要调用绑定表达式 UpdateSource(( 方法将更改发送回模型。 因为您只提到在 DataGrid 的绑定上设置了显式,所以我猜您只需要确保在直接绑定回模型的任何属性上显式设置了该模式。 例如在上述情况下,文本框的文本绑定。 这可能会解决您的问题,但需要您以一种或另一种方式在每个目标的 BindingExpression 上调用 UpdateSource((。
如果您使用的是主流ORM之一(EF,Linq to SQL等(,那么您的实体可能会自动实现INotifyPropertyChanged和INotifyPropertyChange。 由于您正在共享对单个实例的引用,因此编辑中的所有更改都将反映在主视图中以及绑定到该实例的任何其他内容中。 作为更脏的替代方法,您可以创建一个相同类型的单独实例,并在窗口的对话框结果为 true 时手动将值复制回去。
第一种方法要求您手动更新绑定,第二种方法要求您手动更新 Edit 实例中的值。
通过更多代码,我可以帮助您使用特定方法。