我正在尝试创建撤消/重做系统。当前,当用户做某事时,原始对象和新对象按照“动作”被列入列表中。如果我按下撤销按钮,我想再次将原始值分配给新值。
我已经能够在列表中同时获取新对象和原始对象,但是使用我制作的撤消再次分配旧对象时会出错。它会在主列表中更新,该列表包含可以更改的所有对象,但在视图中不会更新。
这是如何撤消方法:
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");
}
}
答案 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:强>
我不认为我可以在这里全面了解,目前尚不清楚你想要更新什么以及你正在使用哪些类。您的示例包含for
,if
和break
,但没有XAML!在讨论WPF技术时,这真的很重要吗?我怎么能确定错误不存在? 分解任务。分解它没有悔意。无论您的业务如何,创建一个小项目,获取项目集合并使用wpf进行游戏。如果你这样做,70%的可能性你会自己找到根本原因,20%成功google,并且提出问题可以帮助你解决其余10%的情况。
答案 2 :(得分:0)
尝试RaisePropertyChanged();当从peoperty setter中使用时,它不需要参数