MVVM OnPropertyChanged在使用赋值操作符时不改变视图(PropertyChanged变为null)

本文关键字:视图 PropertyChanged 变为 null 改变 OnPropertyChanged 赋值操作符 MVVM | 更新日期: 2023-09-27 17:50:55

我正在尝试创建一个撤消/重做系统。目前,当用户做某事时,原始对象和新对象被复制到每个"动作"的列表中。如果我按下撤销按钮,我想重新将原始值赋给新值。

我已经能够在列表中获得新的和原始对象,但是当使用我所做的撤消再次分配旧对象时,它会出错。它在主列表中更新,主列表中包含所有可以更改的对象,但它不会在视图中更新。

这是撤消方法的方法:

for (int t = 0; t < mainData.GroupModelList.Count; ++t)
{
    if (mainData.GroupModelList[t].Name == commandList.ElementAt(position).groupModelNew.Name)
    {
        mainData.GroupModelList[t] = new ViewModels.GroupViewModel(commandList.ElementAt(position).groupModelOrig);
        break;
    }
}

调用GroupViewModel的构造函数:

public GroupViewModel(GroupViewModel selectedGroup)
{ 
    groupModel = new GroupModel();
    // values are assigned from the selectedGroup here (which is the original object in the UndoRedo part)
    // ...
    OnPropertyChanged(null);
 }
这是OnPropertyChanged方法:
private void OnPropertyChanged(string Property)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(Property));
    }
} 

我在某个地方读到,在PropertyChangedEventArgs使用"null"使一切更新,所以这就是我所尝试的,但它不起作用。
在更多的断点之后,我注意到当调用新的构造函数时,PropertyChanged为null,这可能是问题所在。虽然没有撤消/重做,它也可以工作。(当使用文本框或类似的东西简单地改变对象保存的值时)

我也读到我应该把DataContext指向对象本身,但这似乎是不可能的,因为对象没有DataContext属性。

编辑:有人告诉我应该使用ObservableCollection。我已经在用了。如下所示:(这是View可以访问的列表)

private ObservableCollection<GroupViewModel> groupModelList = new ObservableCollection<GroupViewModel>();
public ObservableCollection<GroupViewModel> GroupModelList
{
    get { return groupModelList; }
}

编辑:这是如何绑定到视图:
首先,这是XAML

中的绑定
<Window.Resources>
    <vm:MainViewModel x:Key="MainViewModel" />
</Window.Resources>

MainViewModel保存了一个类型为MainData的对象,并且在该类中有一个ObservableCollection<GroupViewModel>
例如,这是将列表中所选项目的名称绑定到视图中的文本框的代码:(第一行是显示GroupViewModel列表中所有项目的ListBox,第二行是我想作为示例给出的textbox)

<ListBox DisplayMemberPath="Name" Height="412" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource MainViewModel}, Path=mainData.FilteredGroupModelList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10,44,0,0" Name="lbFoundItems" SelectedItem="{Binding Source={StaticResource MainViewModel}, Path=SelectedGroup, Mode=OneWayToSource}" VerticalAlignment="Top" Width="250" SelectionMode="Single" />
<ComboBox Height="23" HorizontalAlignment="Left" ItemsSource="{Binding ElementName=lbFoundItems, Path=SelectedItem.Types, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="436,378,0,0" Name="cmbTypes" SelectedItem="{Binding Source={StaticResource MainViewModel}, Path=SelectedType, Mode=OneWayToSource}" VerticalAlignment="Top" Width="180" />

这也是SelectedGroup变量,它保存对ListBox中所选项的引用:

private GroupViewModel selectedGroup;
public GroupViewModel SelectedGroup
{
    get { return selectedGroup; }
    set
    {
        selectedGroup = value;
        OnPropertyChanged("SelectedGroup");
    }
}

MVVM OnPropertyChanged在使用赋值操作符时不改变视图(PropertyChanged变为null)

什么是"一切",应该在这里更新?想一下,没有什么神奇的:绑定到对象实例的UI元素被订阅到PropertyChanged,这就是为什么当它触发时它们会被更新。

乌利希期刊指南:我不认为我可以在这里得到一个完整的图片,它不清楚你试图更新什么和你使用什么类。您的示例包含forifbreak,但没有XAML!在讨论WPF机制时,这真的很重要吗?我怎样才能确定bug不在那里?分解任务。毫无悔意地分解它。创建一个小项目,收集物品和玩wpf,不管你的业务。当你这样做的时候,70%的机会你会自己找到根本原因,20%的机会谷歌成功,问这个问题会帮助你解决剩下的10%的情况。

问题是,您正在通过使用这行代码创建一个新对象来更改列表控件中项目的DataContext

mainData.GroupModelList[t] = new ViewModels.GroupViewModel(commandList.ElementAt(position).groupModelOrig);

绑定到mainData.GroupModelListItemsControl需要被通知集合已经更改,而不是单独的ViewModel对象已经更新。

确保GroupModelListObservableCollection<T>,因为它实现了INotifyCollectionChanged

编辑:"你有什么建议我应该怎么做吗?"

这叫做纪念品图案。将它与Stack结合使用,实现完整的应用程序撤销/重做功能。备忘录模式

try RaisePropertyChanged();当在属性设置器

中使用时,它不需要参数。