using DTS.Common.Enums; using DTS.Common.Utilities.Logging; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Windows; using System.Windows.Controls; using Microsoft.Xaml.Behaviors; using DTS.Common.Classes; using DTS.Common.Interface.Sensors.SensorsList; using DTS.Common.Interface.TestSetups.TestSetupsList; namespace DTS.Common.Behaviors { public class MultiSelectionBehavior : Behavior { protected override void OnAttached() { base.OnAttached(); if (SelectedItems != null) { AssociatedObject.SelectedItems.Clear(); foreach (var item in SelectedItems) { AssociatedObject.SelectedItems.Add(item); } } } public IList SelectedItems { get => (IList)GetValue(SelectedItemsProperty); set => SetValue(SelectedItemsProperty, value); } public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionBehavior), new UIPropertyMetadata(null, SelectedItemsChanged)); private static void SelectedItemsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var behavior = o as MultiSelectionBehavior; if (behavior == null) return; if (e.OldValue is INotifyCollectionChanged oldValue) { oldValue.CollectionChanged -= behavior.SourceCollectionChanged; behavior.AssociatedObject.SelectionChanged -= behavior.ListBoxSelectionChanged; } if (e.NewValue is INotifyCollectionChanged newValue) { behavior.AssociatedObject.SelectedItems.Clear(); foreach (var item in (IEnumerable)newValue) { behavior.AssociatedObject.SelectedItems.Add(item); } behavior.AssociatedObject.SelectionChanged += behavior.ListBoxSelectionChanged; newValue.CollectionChanged += behavior.SourceCollectionChanged; } } private bool _isUpdatingTarget; private bool _isUpdatingSource; private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (_isUpdatingSource) return; try { _isUpdatingTarget = true; if (e.OldItems != null) { foreach (var item in e.OldItems) { AssociatedObject.SelectedItems.Remove(item); } } if (e.NewItems != null) { foreach (var item in e.NewItems) { AssociatedObject.SelectedItems.Add(item); } } if (e.Action == NotifyCollectionChangedAction.Reset) { AssociatedObject.SelectedItems.Clear(); } } finally { _isUpdatingTarget = false; } } private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { if (_isUpdatingTarget) return; var selectedItems = SelectedItems; if (selectedItems == null) return; //this could be a bulk operation, turn off notifications if consumer is paying attention SelectedItemsStatus.SetUpdating(SelectedItems, true); var itemsToRemove = new List(); try { _isUpdatingSource = true; foreach (var item in e.RemovedItems) { itemsToRemove.Add(item); } var itemsToAdd = new List(); foreach (var item in e.AddedItems) { if (!selectedItems.Contains(item)) { itemsToAdd.Add(item); } } var parentType = selectedItems.GetType(); var type = selectedItems.GetType().GenericTypeArguments[0]; if (parentType.IsGenericType && parentType.GetGenericTypeDefinition() == typeof(BulkObservableCollection<>) && type == typeof(IAnalogSensor)||type == typeof(ITestSetup)) { BulkOperations(itemsToRemove, itemsToAdd, selectedItems, type); } else { RemoveItems(itemsToRemove, selectedItems); AddItems(itemsToAdd, type, selectedItems); } } finally { _isUpdatingSource = false; } } private static void BulkOperations(List itemsToRemove, IList itemsToAdd, IList selectedItems, Type type) { switch (type.Name) { case "IAnalogSensor": SelectedItemsStatus.SetUpdating(selectedItems, false); BulkOperationsAnalogSensor(itemsToRemove, itemsToAdd, selectedItems); break; case "ITestSetup": SelectedItemsStatus.SetUpdating(selectedItems, false); BulkOperationsTestSetup(itemsToRemove, itemsToAdd, selectedItems); break; } } private static void BulkOperationsAnalogSensor(List itemsToRemove, IList itemsToAdd, IList selectedItems) { var collection = selectedItems as BulkObservableCollection; var sensorsToAdd = itemsToAdd.Cast().ToArray(); var sensorsToRemove = itemsToRemove.Cast().ToArray(); RemoveItems(sensorsToRemove, collection); AddItems(sensorsToAdd, collection); } private static void BulkOperationsTestSetup(List itemsToRemove, IList itemsToAdd, IList selectedItems) { var collection = selectedItems as BulkObservableCollection; var toAdd = itemsToAdd.Cast().ToArray(); var toRemove = itemsToRemove.Cast().ToArray(); RemoveItems(toRemove, collection); AddItems(toAdd, collection); } private static void RemoveItems(List itemsToRemove, IList selectedItems) { if (null == itemsToRemove || null == selectedItems) { return; } foreach (var item in itemsToRemove) { selectedItems.Remove(item); } } private static void RemoveItems(IAnalogSensor[] itemsToRemove, BulkObservableCollection collection) { if (null == itemsToRemove || !itemsToRemove.Any()) { return; } if (null == collection) { return; } collection.RemoveRange(itemsToRemove); } private static void RemoveItems(ITestSetup[] itemsToRemove, BulkObservableCollection collection) { if (null == itemsToRemove || !itemsToRemove.Any()) { return; } if (null == collection) { return; } collection.RemoveRange(itemsToRemove); } private static void AddItems(ITestSetup[] itemsToAdd, BulkObservableCollection collection) { if (null == itemsToAdd || !itemsToAdd.Any()) { return; } if (null == collection) { return; } collection.AddRange(itemsToAdd); } private static void AddItems(IAnalogSensor[] itemsToAdd, BulkObservableCollection collection) { if (null == itemsToAdd || !itemsToAdd.Any()) { return; } if (null == collection) { return; } collection.AddRange(itemsToAdd); } private void AddItems(List itemsToAdd, Type type, IList selectedItems) { foreach (var item in itemsToAdd) { if (item == itemsToAdd[itemsToAdd.Count-1]) { //if this is the last item, turn notifications back on SelectedItemsStatus.SetUpdating(SelectedItems, false); } try { if (type.IsInstanceOfType(item)) { selectedItems.Add(item); } } catch (Exception ex) { APILogger.Log(ex); } } } } }