2

我正在使用 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我不想这样做的 . 你有什么想法,如何防止这种行为?我希望只有在单击按钮后才能进行数据绑定。否则数据绑定工作得很好,所以按钮(禁用/启用)在单击后启用和反映对数据库和集合的更改。两个视图都由不同的 ViewModel 提供服务,视图之间的数据通过触发事件传递。

我试图添加到DataGrid UpdateSourceTrigger=ExplicitItemsSource 绑定,但没有帮助。也许,我错过了一些应用程序逻辑?

非常感谢您的帮助。

4

3 回答 3

1

这是大多数 WPF 开发人员犯错误的地方!

在 MVVM 中,脏数据可以存储在ViewModelVM 层中!它模仿了ViewfromModel的观点,并且因为View是错误的,所以ViewModel也会在错误中。那是完全有效的。

话虽如此,问题仍然存在

您将如何不允许临时/数据流向您的 ObservableCollection?

两种方式...

  1. 如果您ObservableCollection特定于您的模型类(例如MyItem),那么如果您的模型类(MyItem)是一个实体类\DAL 类\NHibernate 类,则创建一个MyItem名为ViewModelMyItem然后的类的包装器,而不是ObservableCollection<MyItem>使用ObservableCollection<ViewModelMyItem>

    这样,来自您的脏数据View将在内部,并且只有在单击按钮时ViewModelMyItem才能合法地飞回您的模型类(MyItem) 。Save这意味着在Save Command' 的委托中,如果验证正常,Execute()您可以将 ' 的属性复制ViewModelMyItem到' 的属性中。ItemViewModelMyItem

    因此,如果Item是一个EntityType类/NHibernate类/WCF客户端模型类,它总是只有有效数据,因为ViewModelMyItem它预先过滤了临时/脏信息。

  2. 您可以使用Explicit绑定模型。除非明确调用,否则它会阻止TwoWay数据流回源。ItemBindingExpressions.UpdateSource()

    但据我说,这以直接的方式击败了 MVVM,因为ViewModel不会有 UI 显示的内容!但是,您仍然可以使用 * Attached Behavior *通过留在 MVVM 空间中来管理显式绑定!

让我知道这是否有帮助!

于 2012-05-15T05:21:50.830 回答
0

您最好将代码放入域对象的属性设置器中。然后通过触发处理程序与视觉效果同步NotifyPropertyChanged

有关此主题的更多信息:http:
//msdn.microsoft.com/en-us/library/ms743695.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

于 2012-05-14T20:57:00.447 回答
0

将绑定模式设置为显式应该要求您调用绑定表达式 UpdateSource() 方法将更改发送回您的模型。因为您只提到您在 DataGrid 的绑定上设置了 Explicit,所以我猜您只需要确保在直接绑定回您的模型的任何属性上明确设置了该模式。比如你的 TextBox 的 Text Binding,在上面的例子中。这可能会解决您的问题,但需要您以一种或另一种方式在每个目标的 BindingExpression 上调用 UpdateSource() 。

如果您使用主流 ORM 之一(EF、Linq to SQL 等),那么您的实体很可能会自动实现 INotifyPropertyChanged 和 INotifyPropertyChanging。因为您正在共享对您的单个实例的引用,所以您编辑中的所有更改都将反映在您的主视图以及绑定到该实例的任何其他内容中。作为更肮脏的替代方案,您可以只创建一个相同类型的单独实例,并在窗口的对话框结果为真时手动将值复制回来。

第一种方法需要您手动更新绑定,第二种方法需要您手动更新 Edit 实例中的值。

使用更多代码,我可以帮助您采用特定方法。

于 2012-05-14T23:49:57.547 回答