在使用对话框时,我无法恢复和重做以正确行为。
我有一个简单的模型,它的属性指示对象(running
、paused
、stopped
)的状态,可以通过对话框来修改。所发生的情况是,我得到的操作似乎在撤消队列中什么都不做,或者撤销将对象还原到中间状态。
模型对象在构造函数中用memento注册。对话框有三个单选按钮,每个按钮代表三种不同状态中的一种。每个单选按钮都绑定到每个命令。每个命令都执行属性的更改。我尝试了两种不同的方法,要么每个命令直接在对象中设置属性,要么每个命令在调用时为视图模型设置一个实例变量,然后使用Saving修改对象。
如果使用第一种方法,则在对话框中单击Ok之前,如果用户单击多个无线电按钮,则将每个属性更改放到撤消队列中。试图通过将整个对话框包装成一个批处理来解决这个问题,但结果是取消状态更改,对象将恢复到它在最后一个状态之前的状态,也就是说,如果该属性在对话框打开之前设置为stopped
,并且用户按下暂停无线电按钮,然后启动一个,最后确定,撤销将将该属性设置为paused
而不是预期的stopped
。
如果使用第二种方法,用户打开对话框,将状态更改为paused
,在对话框中单击Ok,撤销/重做将按预期的方式进行,但如果再次打开对话框并选择取消,则会向撤消队列添加另一个操作,即用户必须单击“撤消”两次才能返回到初始的stopped
-state。
因此,我的问题是,应该如何正确地实现这一点以获得预期的行为:每个对话框的交互都可以取消,而不是对话中的每一个交互?
下面是ViewModel的代码:
namespace UndoRedoTest.ViewModels
{
using Catel.Data;
using Catel.MVVM;
public class StartStopViewModel : ViewModelBase
{
Machine.MachineState _state;
public StartStopViewModel(Machine controlledMachine)
{
ControlledMachine = controlledMachine;
_state = controlledMachine.State;
StartMachine = new Command(OnStartMachineExecute);
PauseMachine = new Command(OnPauseMachineExecute);
StopMachine = new Command(OnStopMachineExecute);
Saving += StartStopViewModel_Saving;
}
void StartStopViewModel_Saving(object sender, SavingEventArgs e)
{
ControlledMachine.State = _state;
}
[Model]
public Machine ControlledMachine
{
get { return GetValue<Machine>(ControlledMachineProperty); }
private set { SetValue(ControlledMachineProperty, value); }
}
public static readonly PropertyData ControlledMachineProperty = RegisterProperty("ControlledMachine", typeof(Machine));
public override string Title { get { return "Set Machine state"; } }
public Command StartMachine { get; private set; }
public Command PauseMachine { get; private set; }
public Command StopMachine { get; private set; }
private void OnStartMachineExecute()
{
_state = Machine.MachineState.RUNNING;
//ControlledMachine.SecondState = Machine.MachineState.RUNNING;
}
private void OnPauseMachineExecute()
{
_state = Machine.MachineState.PAUSED;
//ControlledMachine.SecondState = Machine.MachineState.PAUSED;
}
private void OnStopMachineExecute()
{
_state = Machine.MachineState.STOPPED;
//ControlledMachine.SecondState = Machine.MachineState.STOPPED;
}
}
}
发布于 2014-09-09 03:32:24
首先,不要订阅Saving,而只是重写Save()方法。注意,Catel在用ModelAttribute装饰模型时为您处理模型状态。因此,您需要获得对话框的预状态和后置状态,然后将结果集推到批处理中。
例如,我将为对象类(或模型类)创建如下扩展方法:
public static Dictionary<string, object> GetProperties(this IModel model)
{
// todo: return properties
}
然后在Initialize和Save方法中这样做,您将拥有2组属性(预状态和post状态)。现在,我们可以很容易地计算出这些差异:
public static Dictionary<string, object> GetChangedProperties(Dictionary<string, object> preState, Dictionary<string, object> postState)
{
// todo: calculate difference
}
现在您有了区别,您可以创建一个备忘录批处理,它将恢复您预期的确切状态。
ps。如果你能把它写进一篇博客文章,或者用这个功能创建一个公关,那就太好了。
https://stackoverflow.com/questions/25727174
复制相似问题