问题
So I'm having this problem that hopefully you can help with.
I'm writing a WPF application using MVVM Light as a framework. In this situation, I have a list of items, and the SelectedItem is bound to a details view where the user can edit the item. There is a Save button in this case for explicit saving of data.
My problem is that when the user edits the data, the changes immediately shows up in the list. If the user cancels, it resets the selected item, but it's still changed. How do I prevent changes from propogating?
I tried to implement a cloning implementation, but as soon as I did that, MVVM Light's messaging system ends up getting into a loop, resulting in a StackOverflowException due to the fact that I keep cloning the object. As well, the clone implementation is ugly.
Any idea on how I can do this properly?
EDIT:
Basic XAML for list view:
<DataGrid DataContext="{Binding SubJobTypes}"
ItemsSource="{Binding}"
SelectedItem="{Binding ElementName=Root, Path=DataContext.SelectedSubJobType, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
Basic XAML for edit view:
<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 are standard, won't bother posting
回答1:
Instead of disabling the binding mechanism you should have two view models, one for the list items and one for the detail view. Once the an item is selected the list view model sends a property changed changed message. The detail view model then loads the items data, or clones the model and intializes itself with the data. Now the detail view model can alter its local instance of the model.
Once finished the data is saved to the database and the detail view model sends a message that the item has changed. The list view model now receives the message and can use the model to change its item view model, or you can reload the item model from the database and then update the item view model.
This way you do not have to mess around with manually writing the values to the model and if you only clone the model you should not run into any problems with the messaging.
回答2:
It would appear that you are (Two-way) binding to the same object in the ViewModel in both the Master and Detail views.
Possible alternatives are to:
- create a copy of the object
- create additional parameters in your ViewModel, such as "EditName", and bind them to the edit view instead of the name. They would initially be set to the same value as your Name property. On Save, you would set this.Name = this.EditName. On cancel, you would set this.EditName = this.Name.
回答3:
I think you might want to disable "TwoWay" databinding and only write data back to the model when the user presses the Submit button.
来源:https://stackoverflow.com/questions/6457684/problem-with-mvvm-implementation-changes-to-selected-item-propogate-to-list-do