Wpf MVVM实现的问题:对所选项目的更改将发布到列表,不希望这样
所以我遇到了这个问题,希望你能帮我解决 我正在使用MVVM Light作为框架编写一个WPF应用程序。在这种情况下,我有一个项目列表,SelectedItem绑定到用户可以编辑项目的详细信息视图。在这种情况下,有一个保存按钮用于显式保存数据 我的问题是,当用户编辑数据时,更改会立即显示在列表中。如果用户取消,则会重置所选项目,但仍会更改。如何防止更改传播 我试图实现一个克隆实现,但一旦我实现了,MVVM Light的消息传递系统就会陷入循环,导致StackOverflowException,因为我一直在克隆对象。同样,克隆实现也很难看 你知道我该怎么做吗 编辑: 列表视图的基本XAML:Wpf MVVM实现的问题:对所选项目的更改将发布到列表,不希望这样,wpf,data-binding,mvvm,mvvm-light,Wpf,Data Binding,Mvvm,Mvvm Light,所以我遇到了这个问题,希望你能帮我解决 我正在使用MVVM Light作为框架编写一个WPF应用程序。在这种情况下,我有一个项目列表,SelectedItem绑定到用户可以编辑项目的详细信息视图。在这种情况下,有一个保存按钮用于显式保存数据 我的问题是,当用户编辑数据时,更改会立即显示在列表中。如果用户取消,则会重置所选项目,但仍会更改。如何防止更改传播 我试图实现一个克隆实现,但一旦我实现了,MVVM Light的消息传递系统就会陷入循环,导致StackOverflowException,因为
<DataGrid DataContext="{Binding SubJobTypes}"
ItemsSource="{Binding}"
SelectedItem="{Binding ElementName=Root, Path=DataContext.SelectedSubJobType, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
编辑视图的基本XAML:
<StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal" DataContext="{Binding Path=CurrentSubJobType}">
<TextBlock Text="Name"/>
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" Width="150"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="{Binding Path=SubmitCommandText, FallbackValue=Submit}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=SaveSubJobTypeCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Cancel" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=CancelCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Delete">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=DeleteCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</StackPanel>
</StackPanel>
ViewModels是标准的,不必麻烦发布,我认为您可能希望禁用“双向”数据绑定,并且仅在用户按下提交按钮时将数据写入模型。在主视图和详细视图中,您似乎(双向)绑定到ViewModel中的同一对象 可能的替代方案包括:
- 创建对象的副本
- 在ViewModel中创建其他参数,例如“EditName”,并将其绑定到编辑视图而不是名称。它们最初将设置为与Name属性相同的值。保存时,您可以设置此.Name=this.EditName。取消时,您将设置this.EditName=this.Name
通过这种方式,您不必手动将值写入模型,如果只克隆模型,则不应在消息传递方面遇到任何问题。-1因为这不符合mvvm让绑定处理模型更新的想法。Aproach有缺陷,导致过多的手动和耦合代码。最好使用模型克隆来初始化两个不同的视图模型。MVVM是一种模式,而不是法律。对于违反模式的一次性挑战,一个简单的解决方案并不是“错误的”。。。模型克隆方法是一种有效的方法,但它可能会在一个简单的场景中增加不必要的复杂性。。。(最初的问题并不意味着一个大型复杂的应用程序)假定它不是一项法律(引用Laurent Buginion的话“MVVM警察不会来”)。但它背后有一个想法,即生成可测试且松散耦合的代码。同样的想法也减少了代码(除了由代码片段处理的样板代码),使项目更易于维护。而且。。。它让你保持理智!1.单向绑定不适合此问题。2.是的,这就是方法,但前提是你有两个不同的视图模型,并且模型就是你所说的对象。3.不是很好的设计,因为它使事情复杂化。分开你的顾虑。。。谢谢你的鱼;-)同意-删除了单向约束注释。我也同意,额外的参数不是一个理想的设计(但它是一种可能性)。我当然会选择对象的副本(在一个单独的视图模型中)-它们是单独的视图(即使“编辑”视图在“列表”视图中同时显示)。这就是我所拥有的。我已经有两个视图模型了。但是,消息传递框架从不创建副本,因此当我在“详细信息”视图中修改该项时,它与列表视图中的对象相同。至于克隆对象,我知道这会起作用,但我希望有更好的方法,因为大多数示例都不会克隆对象。我所说的“更好”是指一种解决方案,我不必在每个类中维护映射列表,我需要为每个类维护映射。@CamronBute:您不必维护映射,两个视图模型(项目视图模型和详细视图模型)都基于同一个模型。消息传递完整模型或仅传递ID,具体取决于您是要从数据库加载数据还是使用客户端上缓存的数据。使用序列化/反序列化机制时,可以非常轻松地创建对象的克隆(例如JavaScriptSerializer)。详图有一个LoadMetro,它将模型克隆并分配给私有属性。这是一份现在可以编辑的副本。