MVVM OnPropertyChanged在使用赋值运算符时不更改视图(PropertyChanged变为null)

时间:2015-05-28 08:25:20

标签: c# wpf mvvm

我正在尝试创建撤消/重做系统。当前,当用户做某事时,原始对象和新对象按照“动作”被列入列表中。如果我按下撤销按钮,我想再次将原始值分配给新值。

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

这是如何撤消方法:

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在调用新构造函数时为空,这可能是问题所在。它确实可以在没有Undo / Redo的情况下工作。 (仅使用文本框或类似方法更改对象保存的值时)

我还读过,我应该将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");
    }
}

3 个答案:

答案 0 :(得分:0)

问题是您要通过使用此行代码创建新对象来更改列表控件中项目的DataContext ...

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

绑定到ItemsControl的{​​{1}}需要通知集合已更改,而不是单个mainData.GroupModelList对象已更新。

确保ViewModel在实施GroupModelList时为ObservableCollection<T>

编辑:“你有没有提到我应该怎么做?”

它被称为Memento模式。将它与Stack结合使用可实现完整的应用程序撤销/重做功能。 Integer

答案 1 :(得分:0)

这里应该更新的“一切”是什么?想想它一秒钟,没有魔力:绑定到对象实例的UI元素订阅PropertyChanged,这就是它们触发时更新的原因。

<强> UPD: 我不认为我可以在这里全面了解,目前尚不清楚你想要更新什么以及你正在使用哪些类。您的示例包含forifbreak,但没有XAML!在讨论WPF技术时,这真的很重要吗?我怎么能确定错误不存在? 分解任务。分解它没有悔意。无论您的业务如何,创建一个小项目,获取项目集合并使用wpf进行游戏。如果你这样做,70%的可能性你会自己找到根本原因,20%成功google,并且提出问题可以帮助你解决其余10%的情况。

答案 2 :(得分:0)

尝试RaisePropertyChanged();当从peoperty setter中使用时,它不需要参数