Problems with undomanager

I have changed my Element class to inherit from GraphLinksModelNodeData and in each Setter I call RaisePropertyChanged.

Now if I move a Node and press ctrl-z I get and exception and I can’t really see why:

System.InvalidOperationException was unhandled
HResult=-2146233079
Message=Eine Ausnahme vom Typ “System.InvalidOperationException” wurde ausgelöst.
Source=Northwoods.GoWPF
StackTrace:
bei #nj.#yq.Error(String #iq)
bei Northwoods.GoXam.Model.GraphLinksModelNodeData1.ChangeDataValue(ModelChangedEventArgs e, Boolean undo) bei Northwoods.GoXam.Model.DiagramModel.ChangeDataValue(ModelChangedEventArgs e, Boolean undo) bei Northwoods.GoXam.Model.GraphLinksModel4.ChangeDataValue(ModelChangedEventArgs e, Boolean undo)
bei Northwoods.GoXam.Model.DiagramModel.ChangeModel(ModelChangedEventArgs e, Boolean undo)
bei Northwoods.GoXam.Model.ModelChangedEventArgs.Undo()
bei Northwoods.GoXam.Model.UndoManager.CompoundEdit.Undo()
bei Northwoods.GoXam.Model.UndoManager.Undo()
bei Northwoods.GoXam.CommandHandler.Undo()
bei Northwoods.GoXam.CommandHandler.#H(Object #r, ExecutedRoutedEventArgs #p)
bei System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
bei System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
bei System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
bei System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
bei System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
bei System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
bei System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
bei System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
bei System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
bei System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
bei System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
bei System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
bei System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
bei System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
bei System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated)
bei System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
bei System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
bei System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
bei System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
bei System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
bei System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
bei System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
bei System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
bei System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
bei System.Windows.Input.InputManager.ProcessStagingArea()
bei System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
bei System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
bei System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
bei System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
bei System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
bei System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
bei System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
bei System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
bei System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(MSG& msg, Boolean& handled)
bei System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(MSG& msg, Boolean& handled)
bei System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(MSG& msg)
bei System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.Run()
bei System.Windows.Application.RunDispatcher(Object ignore)
bei System.Windows.Application.RunInternal(Window window)
bei System.Windows.Application.Run(Window window)
bei System.Windows.Application.Run()
bei KSCCoreGFX.App.Main() in c:\WorkDir_Trunk\Win\Bfe\Ksc\Apps\KSCCoreGFX\KSCCoreGFX\obj\Debug\App.g.cs:Zeile 0.
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException:

That’s odd. For simple properties there shouldn’t be any problems, as you can see in all of the samples that support undo/redo.

The implementation of GraphLinksModelNodeData.ChangeDataValue is:

    public virtual void ChangeDataValue(ModelChangedEventArgs e, bool undo) {
      if (e == null) return;
      if (e.PropertyName == "Location") {
        this.Location = (Point)e.GetValue(undo);
      } else if (e.PropertyName == "Text") {
        this.Text = (String)e.GetValue(undo);
      } else if (e.PropertyName == "Key") {
        this.Key = (NodeKey)e.GetValue(undo);
      } else if (e.PropertyName == "IsSubGraph") {
        this.IsSubGraph = (bool)e.GetValue(undo);
      } else if (e.PropertyName == "IsSubGraphExpanded") {
        this.IsSubGraphExpanded = (bool)e.GetValue(undo);
      } else if (e.PropertyName == "WasSubGraphExpanded") {
        this.WasSubGraphExpanded = (bool)e.GetValue(undo);
      } else if (e.PropertyName == "SubGraphKey") {
        this.SubGraphKey = (NodeKey)e.GetValue(undo);
      } else if (e.PropertyName == "MemberKeys") {
        this.MemberKeys = (IList<NodeKey>)e.GetValue(undo);
      } else if (e.PropertyName == "IsLinkLabel") {
        this.IsLinkLabel = (bool)e.GetValue(undo);
      } else if (e.PropertyName == "Category") {
        this.Category = (String)e.GetValue(undo);
      } else if (e.Change == ModelChange.Property) {
        if (!ModelHelper.SetProperty(e.PropertyName, e.Data, e.GetValue(undo))) {
          ModelHelper.Error("ERROR: Unrecognized property name: " + e.PropertyName != null ? e.PropertyName : "(noname)" + " in GraphLinksModelNodeData.ChangeDataValue");
        }
      }
    }

ModelHelper.SetProperty is an internal method that uses Reflection to set the property. Perhaps there’s something that you have declared to prevent reflection from working? In the debugger, can you see details of any nested exception?

No, I’ve tried to find something, but I see no hint to that problem.
I will take a look again.