/// <summary> /// Returns the <see cref="UndoManager"/> defined in the view model or /// nearest ancestor hierachy. /// </summary> /// <exception cref="NotSupportedException"> /// More than one <see cref="UndoManager"/> is defined in the same ancestor level. /// </exception> /// <exception cref="InvalidOperationException"> /// Undo is enabled but no <see cref="UndoManager"/> is defined in the view model hierarchy. /// </exception> public static UndoManager GetManager(IViewModel vm) { IEnumerable <IViewModel> currentLevel = new IViewModel[] { vm }; do { var undoRootBehaviors = currentLevel .Select(x => { UndoRootBehavior b; x.Descriptor.Behaviors.TryGetBehavior(out b); return(new { VM = x, Behavior = b }); }) .Where(x => x.Behavior != null) .ToArray(); switch (undoRootBehaviors.Length) { case 0: currentLevel = currentLevel .SelectMany(x => x.Kernel.Parents) .ToArray(); break; case 1: var match = undoRootBehaviors.Single(); return(match.Behavior.GetUndoManager(match.VM.GetContext())); default: throw new NotSupportedException(ExceptionTexts.MultipleUndoRoots); } } while (currentLevel.Any()); //throw new InvalidOperationException(ExceptionTexts.NoUndoRootManagerFound); return(null); }