在之前的文章中讲过如何实现撤消重做栈:https://gyrojeff.top/index.php/archives/wpf-implement-undo-redo/

问题引入

之前,我们每定义一个支持撤消重做的属性都要写很多代码:

private string _text; public string Text { get => _text; set => UndoRedoManager.PushAndPerformRecord(o => { var nowValue = Text; SetProperty(ref _text, (string)o); return nowValue; }, o => { var nowValue = Text; o ??= value; SetProperty(ref _text, (string)o); return nowValue; }); }
C

本文的目标是将上述冗长的表达改写成:

private string _text; [Undoable] public string Text { get => _text; set => SetProperty(value); }
C

实现逻辑

代码

public enum BackingNamingStyle { /// <summary> /// Example: "BackingStore" => "_backingStore" /// </summary> UnderscoreAndLowerCase, /// <summary> /// Example: "BackingStore" => "backingStore" /// </summary> LowerCase } public partial class NotifyObject { public bool SetProperty<T>(T value, [CallerMemberName] string propertyName = "", BackingNamingStyle backingNamingStyle = BackingNamingStyle.UnderscoreAndLowerCase, Action beforeChanged = null, Action onChanged = null, UndoRedoRecord.DelegateActionWithAndReturnValue undoAction = null, UndoRedoRecord.DelegateActionWithAndReturnValue redoAction = null, UndoRedoRecord.DelegateActionWithValue disposeAction = null) { var backingName = ""; switch (backingNamingStyle) { case BackingNamingStyle.LowerCase: backingName = propertyName[0].ToString().ToLower() + propertyName.Substring(1); break; case BackingNamingStyle.UnderscoreAndLowerCase: backingName = "_" + propertyName[0].ToString().ToLower() + propertyName.Substring(1); break; } Type type = null; FieldInfo backingInstance = null; do { type = type == null ? GetType() : type.BaseType; if (type == null) return false; backingInstance = type.GetField(backingName, BindingFlags.NonPublic | BindingFlags.Instance); } while (backingInstance == null); if (EqualityComparer<T>.Default.Equals((T)backingInstance.GetValue(this), value)) return false; var attribute = GetType().GetProperty(propertyName)?.GetCustomAttribute<Undoable>(); if (attribute == null) { beforeChanged?.Invoke(); backingInstance.SetValue(this, value); onChanged?.Invoke(); RaisePropertyChanged(propertyName); } else { UndoRedoManager.PushAndPerformRecord(undoAction ?? (o => { var nowValue = backingInstance.GetValue(this); backingInstance.SetValue(this, o); RaisePropertyChanged(propertyName); return nowValue; }), redoAction ?? (o => { var nowValue = backingInstance.GetValue(this); o ??= value; backingInstance.SetValue(this, o); RaisePropertyChanged(propertyName); return nowValue; }), disposeAction); } return true; } }
C
最后修改:2021 年 11 月 30 日 04 : 38 PM
真的不买杯奶茶嘛....qwq