/// <summary> /// Has the last undone operation redone. /// </summary> /// <param name="undoRedoLevel">A level of undo, with contents.</param> /// <param name="toInvokeOutsideLock">An action to invoke outside of the lock.</param> /// <param name="state">The state object to pass to the invocation.</param> /// <returns><see langword="true" /> if the redo was successful, <see langword="false" /> otherwise.</returns> protected override bool RedoInternally( StateChangeBase undoRedoLevel, out Action <object?>?toInvokeOutsideLock, out object?state) { if (base.RedoInternally( undoRedoLevel, out toInvokeOutsideLock, out state)) { return(true); } switch (undoRedoLevel) { case AddStateChange <KeyValuePair <TKey, TValue> >(var(key, value), _): { IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; _ = container.Add( key, value); toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } case RemoveStateChange <KeyValuePair <TKey, TValue> >(_, var keyValuePair): { IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; _ = container.Remove(keyValuePair.Key); toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } case ClearStateChange <KeyValuePair <TKey, TValue> > : { InternalContainer.Clear(); toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } case DictionaryAddStateChange <TKey, TValue>(var key, var value): { IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; _ = container.Add( key, value); toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } case DictionaryRemoveStateChange <TKey, TValue>(var key, _): { IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; _ = container.Remove(key); toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } case DictionaryChangeStateChange <TKey, TValue>(var key, var newValue, _): { IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; container[key] = newValue; toInvokeOutsideLock = innerState => { if (innerState == null) { return; } ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange(); }; state = this; break; } default: { toInvokeOutsideLock = null; state = null; return(false); } } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="EditCommittedEventArgs" /> class. /// </summary> /// <param name="stateChanges">The state changes that have been committed.</param> public EditCommittedEventArgs(StateChangeBase stateChanges) => StateChanges = stateChanges;
protected override bool UndoInternally( StateChangeBase undoRedoLevel, out Action <object?>?toInvokeOutsideLock, out object?state) { if (base.UndoInternally( undoRedoLevel, out toInvokeOutsideLock, out state)) { return(true); } switch (undoRedoLevel) { case AddStateChange <T>(var item, var index): { InternalListContainer.RemoveAt(index); if (ItemsAreUndoable && AutomaticallyCaptureSubItems && item is IUndoableItem { IsCapturedIntoUndoContext : true } ul&& ul.ParentUndoContext == this) { ul.ReleaseFromUndoContext(); } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } (var observableListBase, T removedItem, var indexRemoved) = (Tuple <ObservableListBase <T>, T, int>)innerState; observableListBase.RaiseCollectionChangedRemove( removedItem, indexRemoved); observableListBase.RaisePropertyChanged(nameof(observableListBase.Count)); observableListBase.ContentsMayHaveChanged(); }; state = new Tuple <ObservableListBase <T>, T, int>( this, item, index); break; } case AddMultipleStateChange <T>(var addedItems, var index): { for (var i = 0; i < addedItems.Length; i++) { InternalListContainer.RemoveAt(index); } IEnumerable <T> items = addedItems; if (ItemsAreUndoable && AutomaticallyCaptureSubItems) { foreach (IUndoableItem ul in items.Cast <IUndoableItem>() .Where( ( p, thisL1) => p.IsCapturedIntoUndoContext && p.ParentUndoContext == thisL1, this)) { ul.ReleaseFromUndoContext(); } } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } var(observableListBase, enumerable, addedIndex) = (Tuple <ObservableListBase <T>, IEnumerable <T>, int>)innerState; observableListBase.RaiseCollectionChangedRemoveMultiple( enumerable, addedIndex); observableListBase.RaisePropertyChanged(nameof(observableListBase.Count)); observableListBase.ContentsMayHaveChanged(); }; state = new Tuple <ObservableListBase <T>, IEnumerable <T>, int>( this, items, index); break; } case RemoveStateChange <T>(var index, var item): { InternalListContainer.Insert( index, item); if (ItemsAreUndoable && AutomaticallyCaptureSubItems && item is IUndoableItem { IsCapturedIntoUndoContext : false } ul) { ul.CaptureIntoUndoContext(this); } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } (var observableListBase, T removedItem, var removedIndex) = (Tuple <ObservableListBase <T>, T, int>)innerState; observableListBase.RaiseCollectionChangedAdd( removedItem, removedIndex); observableListBase.RaisePropertyChanged(nameof(observableListBase.Count)); observableListBase.ContentsMayHaveChanged(); }; state = new Tuple <ObservableListBase <T>, T, int>( this, item, index); break; } case RemoveMultipleStateChange <T>(var indexes, var items): { for (var i = items.Length - 1; i >= 0; i--) { InternalListContainer.Insert( indexes[i], items[i]); } if (ItemsAreUndoable && AutomaticallyCaptureSubItems) { foreach (IUndoableItem ul in items.Cast <IUndoableItem>() .Where(p => !p.IsCapturedIntoUndoContext)) { ul.CaptureIntoUndoContext(this); } } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } var(observableListBase, enumerable, indexesInternal) = (Tuple <ObservableListBase <T>, IEnumerable <T>, IEnumerable <int> >)innerState; observableListBase.RaiseCollectionChangedAddMultiple( enumerable, indexesInternal); observableListBase.RaisePropertyChanged(nameof(observableListBase.Count)); observableListBase.ContentsMayHaveChanged(); }; state = new Tuple <ObservableListBase <T>, IEnumerable <T>, IEnumerable <int> >( this, items, indexes); break; } case ClearStateChange <T>(var originalItems): { foreach (T t in originalItems) { _ = InternalListContainer.Add(t); } if (ItemsAreUndoable && AutomaticallyCaptureSubItems) { foreach (IUndoableItem ul in originalItems.Cast <IUndoableItem>() .Where(p => !p.IsCapturedIntoUndoContext)) { ul.CaptureIntoUndoContext(this); } } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } var convertedState = (ObservableListBase <T>)innerState; convertedState.RaiseCollectionReset(); convertedState.RaisePropertyChanged(nameof(convertedState.Count)); convertedState.ContentsMayHaveChanged(); }; state = this; break; } case ChangeAtStateChange <T>(var index, var oldItem, var newItem): { InternalListContainer[index] = newItem; if (ItemsAreUndoable && AutomaticallyCaptureSubItems) { if (newItem is IUndoableItem { IsCapturedIntoUndoContext : false } ul) { ul.CaptureIntoUndoContext(this); } if (oldItem is IUndoableItem { IsCapturedIntoUndoContext : true } ol&& ol.ParentUndoContext == this) { ol.ReleaseFromUndoContext(); } } toInvokeOutsideLock = innerState => { if (innerState == null) { return; } (var observableListBase, T oldItemInternal, T newItemInternal, var indexInternal) = (Tuple <ObservableListBase <T>, T, T, int>)innerState; observableListBase.RaiseCollectionChangedChanged( oldItemInternal, newItemInternal, indexInternal); observableListBase.RaisePropertyChanged(nameof(observableListBase.Count)); observableListBase.ContentsMayHaveChanged(); }; state = new Tuple <ObservableListBase <T>, T, T, int>( this, oldItem, newItem, index); break; } default: { toInvokeOutsideLock = null; state = null; return(false); } } return(true); }