/// <summary> /// Initializes a new instance of the <see cref="KeyedCommandifiedList<T, TKeyValue>"/> class. /// </summary> /// <param name="keyValueProducerFunc">The key value producer func.</param> /// <param name="keyPropertyName">Name of the key property which is used to track changes in individual elements.</param> /// <param name="isSynchronized">if set to <c>true</c> this list is a synchronized collection, using a lock on SyncRoot to synchronize activity in multithreading scenarios</param> public KeyedCommandifiedList(Func <T, TKeyValue> keyValueProducerFunc, string keyPropertyName, bool isSynchronized) : base(isSynchronized) { ArgumentVerifier.CantBeNull(keyValueProducerFunc, "keyValueProducerFunc"); ArgumentVerifier.CantBeNull(keyPropertyName, "keyPropertyName"); _elementPerKeyValue = new MultiValueDictionary <TKeyValue, T>(); _keyValuePerElement = new Dictionary <T, TKeyValue>(); _keyValueProducerFunc = keyValueProducerFunc; _keyPropertyName = keyPropertyName; }
/// <summary> /// Determines whether this dictionary contains the specified value for the specified key /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>true if the value is stored for the specified key in this dictionary, false otherwise</returns> public bool ContainsValue(TKey key, TValue value) { ArgumentVerifier.CantBeNull(key, "key"); bool toReturn = false; HashSet <TValue> values = null; if (this.TryGetValue(key, out values)) { toReturn = values.Contains(value); } return(toReturn); }
/// <summary> /// Adds the specified value under the specified key /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void Add(TKey key, TValue value) { ArgumentVerifier.CantBeNull(key, "key"); HashSet <TValue> container = null; if (!this.TryGetValue(key, out container)) { container = new HashSet <TValue>(); base.Add(key, container); } container.Add(value); }
/// <summary> /// Removes the specified value for the specified key. It will leave the key in the dictionary. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void Remove(TKey key, TValue value) { ArgumentVerifier.CantBeNull(key, "key"); HashSet <TValue> container = null; if (this.TryGetValue(key, out container)) { container.Remove(value); if (container.Count <= 0) { this.Remove(key); } } }
/// <summary> /// Converts an enumerable into a MultiValueDictionary. Similar to ToDictionary however this time the returned type is a MultiValueDictionary. /// </summary> /// <typeparam name="TKey">The type of the key.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="source">The source.</param> /// <param name="keySelectorFunc">The key selector func.</param> /// <returns>MultiValueDictionary with the values of source stored under the keys retrieved by the keySelectorFunc which is applied to each /// value in source, or null if source is null</returns> public static MultiValueDictionary <TKey, TValue> ToMultiValueDictionary <TKey, TValue>(this IEnumerable <TValue> source, Func <TValue, TKey> keySelectorFunc) { if (source == null) { return(null); } ArgumentVerifier.CantBeNull(keySelectorFunc, "keySelectorFunc"); MultiValueDictionary <TKey, TValue> toReturn = new MultiValueDictionary <TKey, TValue>(); foreach (TValue v in source) { toReturn.Add(keySelectorFunc(v), v); } return(toReturn); }
/// <summary> /// Sets the state of this collection to the passed in state. This means: removing all elements and then setting it back to the state passed in. /// </summary> /// <param name="state">The state.</param> private void SetCurrentState(IList <T> state) { ArgumentVerifier.CantBeNull(state, "state"); base.ClearItems(); // from back to front, insert the items, in the same order. for (int i = state.Count - 1; i >= 0; i--) { T itemToAdd = state[i]; OnAddingItem(itemToAdd); base.InsertItem(0, itemToAdd); OnAddingItemComplete(itemToAdd); } NotifyChange(ListChangedType.Reset, -1, -1); }
/// <summary> /// Splits the pairs in the enumerable into two lists of values where the pair at position x in source equals to values1[x], values2[x] /// </summary> /// <typeparam name="TValue1">The type of the Value1 property.</typeparam> /// <typeparam name="TValue2">The type of the Value2 property.</typeparam> /// <typeparam name="TValue3">The type of the elements in values1. TValue1 has to be casteable to TValue3.</typeparam> /// <typeparam name="TValue4">The type of the eleemnts in values2. TValue2 has to be casteable to TValue4.</typeparam> /// <param name="source">The source.</param> /// <param name="values1">The list of all Value1 values in the pairs in source.</param> /// <param name="values2">The list of all Value2 values in the pairs in source.</param> public static void SplitPairs <TValue1, TValue2, TValue3, TValue4>(this IEnumerable <Pair <TValue1, TValue2> > source, List <TValue3> values1, List <TValue4> values2) where TValue3 : TValue1 where TValue4 : TValue2 { ArgumentVerifier.CantBeNull(values1, "values1"); ArgumentVerifier.CantBeNull(values2, "values2"); if (source == null) { return; } foreach (Pair <TValue1, TValue2> pair in source) { values1.Add((TValue3)pair.Value1); values2.Add((TValue4)pair.Value2); } }
/// <summary> /// Calls the specified to call after intervalMS milliseconds, unless a call is already in progress, in which case the call is ignored. It doesn't matter if /// this method was called previously with a different toCall value. /// </summary> /// <param name="toCall">The func to call.</param> /// <param name="intervalMS">The interval to wait, in ms, before toCall is called. If interval is below 100, it's clamped to 100.</param> /// <param name="synchronizingObject">The synchronizing object. If null, the call to the lambda specified to <see cref="Call(Action, double, ISynchronizeInvoke)"/> might be done on a different thread, as the System /// timer used is using a threadpool in that case. If the call has to be the same thread as the UI, specify a UI object /// as synchronizingObject, e.g. a form object or control object on which this limiter is used.</param> /// <returns>true if the call is accepted and will be performed in intervalMS ms. False if the call is ignored if a timer is /// already in progress.</returns> public bool Call(Action toCall, double intervalMS, ISynchronizeInvoke synchronizingObject) { ArgumentVerifier.CantBeNull(toCall, "toCall"); lock (_semaphore) { if (_timer.Enabled) { // already in progress return(false); } _eventHandled = false; _toCall = toCall; _timer.SynchronizingObject = synchronizingObject; _timer.Interval = Math.Max(100.0, intervalMS); _timer.Enabled = true; return(true); } }
/// <summary> /// Enqueues the event in the task queue. /// </summary> /// <param name="involvedElement">The involved element. This doesn't have to be the sender. Preverably this is the element involved in the /// event.</param> /// <param name="eventArgs">The TEventArgs instance containing the event data.</param> public void EnqueueEvent(TElement involvedElement, TEventArgs eventArgs) { ArgumentVerifier.CantBeNull(involvedElement, "involvedElement"); ArgumentVerifier.CantBeNull(eventArgs, "eventArgs"); if (!this.Enabled) { this.EventThrottled.RaiseEvent(involvedElement, eventArgs); return; } _taskQueue.Enqueue(new Pair <TElement, TEventArgs>(involvedElement, eventArgs)); if (_timer.Enabled) { // timer already runs, no futher action return; } if (_queueProcessingInProgress) { return; } // not processing, no timer running yet, start timer _timer.Start(); }
private IList _databindingContainer; // for IEditableObject: AddNew() sets this property, CancelEdit has to remove this field from the container. #endregion /// <summary> /// Initializes a new instance of the <see cref="EditableObjectDataContainer"/> class. /// </summary> /// <param name="editedObject">The edited object for which this container implements IEditableObject.</param> public EditableObjectDataContainer(object editedObject) { ArgumentVerifier.CantBeNull(editedObject, "editedObject"); _editedObject = editedObject; }