我有一个wpv/mvvm-light/vb.net应用程序,具有主/明细视图。在这个视图中,有一个客户列表框和客户详细信息的详细视图,用户可以查看和编辑客户。Mvvm - 取消更改Wpf列表框,vb.net
我想添加一个功能,在列表框中选择新客户端时,系统会提示用户保存更改。如果用户从消息框中选择是,然后保存更改,如果没有,则放弃更改并将先前选择的项目返回到其原始值。我有这一切工作正常。
我的问题是,当用户选择一个新的客户端和消息框要求他们保存更改时,列表框不同步。这意味着列表框会显示所选的新客户端,但详细信息视图仍会显示以前的客户端。奇怪的是,它在罕见的情况下正常工作。
以下是我的观点:
<UserControl x:Class="FTC.View.ClientListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FTC_Application"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="900">
<ListBox
Grid.Column="1"
Width="350"
Style="{DynamicResource FTC_ListBox}"
ItemTemplate="{DynamicResource FTC_ClientListTemplate}"
ItemContainerStyle="{DynamicResource FTC_ListItem}"
ItemsSource="{Binding ClientViewSource.View}"
SelectedItem="{Binding Path=Selection, Mode=TwoWay}"
/>
<ContentControl DataContext="{Binding Path=Selection, Mode=TwoWay}" >
<!--all the display stuff goes here for the detail view-->
</ContentControl>
</UserControl>
下面是在列表框的selectedItem属性绑定到视图模型的财产。它也是内容控件的绑定,用于显示细节。
Public Property Selection As client
Get
Return Me._Selection
End Get
Set(ByVal value As client)
''capture current value of selection
_PreviousClient = _Selection
''If they are the same,
If value Is _PreviousClient Then
Return
End If
' Note that we actually change the value for now.This is necessary because WPF seems to query the
' value after the change. The list box likes to know that the value did change.
If Me._Selection.HasChanges = True And _Selection.HasErrors = False Then
'If HasChangesPrompt(value) = True Then
' ''user rejects saving changes, exit property
' Return
'End If
If FTCMessageBox.Show("Do you want to save your changes", "Unsaved Changes", MessageBoxButton.YesNo, MessageBoxImage.Warning) = MessageBoxResult.No Then
''SELECTION IS CANCELLED
' change the value back, but do so after the UI has finished it's current context operation.
Application.Current.Dispatcher.BeginInvoke(New Action(Sub()
'' revert the current selected item to its original values and reset its HasCHanges tracking
objHelper.CopyProperties(_OriginalClient, _Selection)
_Selection.HasChanges = False
RaisePropertyChanged(ClientSelectedPropertyName)
''continue with listbox selection changing to the new value for selection
_ClientCollectionViewSource.View.MoveCurrentTo(value)
End Sub), DispatcherPriority.Normal, Nothing)
Return
Else
''save changes to database
SaveExecute()
End If
End If
_Selection = value
_Selection.HasChanges = False
RaisePropertyChanged(ClientSelectedPropertyName)
''clone the unchanged version of the current selected client on na original variable
objHelper.CopyProperties(_Selection, _OriginalClient)
End Set
End Property
这样的想法是,如果用户不希望保存更改,客户端的原始值复制(使用反射)在当前值,则UI被更新,选择继续上用户选择的新值。但是,就像我上面所说的,列表框不反映这种变化,即使我累了与以下行硬编码:
''continue with listbox selection changing to the new value for selection
_ClientCollectionViewSource.View.MoveCurrentTo(value)
我通过努力定制的解决方案得到了这个解决方案发布HERE
能任何人都可以帮我弄清楚为什么当这种情况发生时我的列表框不同步。
在此先感谢
感谢您的回复。我对setter中的代码量也感到不舒服。但我试图遵循MVVM模式,因此UI视图需要与ViewModel分离。所以我不能在view.xaml对象的事件后面使用简单的代码。因此,我必须在视图模型代码中管理这些,并且在选择更改时执行的唯一代码是选择对象的设置器。所以我把逻辑放在那里取消那个改变。你知道另一种方式,我可以做到这一点。 –