&tag(WPF/Undo); &tag(WPF, Undo); *目次 [#c76f3e45] #contents *参考情報 [#ke8ad5f6] -[[Notify Changed » Blog Archive » Using the Viewmodel pattern to provide Undo / Redo in WPF:http://blog.notifychanged.com/2009/01/30/using-the-viewmodel-pattern-to-provide-undo-redo-in-wpf/]] -[[Notify Changed » Blog Archive » Using MVVM to provide undo/redo. Part 2: Viewmodelling lists:http://blog.notifychanged.com/2009/01/30/viewmodelling-lists/]] -[[danice/MVVMUndoRedo - GitHub:https://github.com/danice/MVVMUndoRedo]]。上記blog記事のサンプルコード。blogには断片的なコードしか示されてないので実際にソースコードを参照したほうがよい。 -[[WPF Undo/Redo Framework:http://wpfundoredo.codeplex.com/]]…WPF用のUndo/Redoフレームワーク。 *[[WPF Undo/Redo Framework:http://wpfundoredo.codeplex.com/]]に関して [#u9ba2c1c] -サンプルはソースコードのダウンロードから入手可能(ダウンロードはDLLのみ)。 -UndoableActionBaseを継承したUndoablePropertyとDelegateUndoableCommandを使う。 -MVVM風にViewModelのプロパティの変更をUndoしたい場合は、次のようにUndoablePropertyを使ってプロパティ定義する。 #pre{{ private UndoableProperty<double> _sliderText; public double SliderText { get { return _sliderText.GetValue(); } set { _sliderText.SetValue(value); } } }} -プロパティの変更はPropertyChangedで通知されるが、Undoは以下の処理によりある程度の時間以内の変更は1つの処理として元に戻される。 #pre{{ /// <summary> /// Tells the context that an action has occurred. /// </summary> /// <param name="action">The action that was executed.</param> /// <param name="data">The data associated with the action.</param> public void ActionExecuted(IUndoableAction action, object data) { object possible = null; if (action is IUndoableProperty && (this.UndoStack.Count > 0 && this.UndoStack.First().Item1 == action.Name)) { if ((DateTime.Now - lastModified).TotalMilliseconds < (action as IUndoableProperty).BatchingTimeout) { possible = this.UndoStack.Pop().Item2; } else { this.lastModified = DateTime.Now; } } else { this.lastModified = DateTime.Now; } if (possible == null) { this.UndoStack.Push(new Tuple<string, object>(action.Name, data)); } else { this.UndoStack.Push(new Tuple<string, object>(action.Name, possible)); } this.RedoStack.Clear(); } }} -プロパティ以外のコマンドをUndoしたい場合次のようにする。サンプルのボタンがおされたときの処理。 #pre{{ public UndoableDelegateCommand<string, char> TypeCharacterCommand { get; set; } public char TypeCharacterCommand_Execute(string s) { var c = s.First(); this.SomeText += c; return c; } public bool TypeCharacterCommand_CanExecute(string s) { if (string.IsNullOrEmpty(s)) { return false; } var c = s.First(); if (char.IsDigit(c)) { return true; } return false; } }}