Files
DP44/Common/DTS.CommonCore/Behaviors/MultiSelectionBehavior.cs
2026-04-17 14:55:32 -04:00

161 lines
5.2 KiB
C#

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 System.Windows.Interactivity;
namespace DTS.Common.Behaviors
{
public class MultiSelectionBehavior : Behavior<ListBox>
{
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);
try
{
_isUpdatingSource = true;
foreach (var item in e.RemovedItems)
{
selectedItems.Remove(item);
}
var itemsToAdd = new List<object>();
foreach (var item in e.AddedItems)
{
if (!selectedItems.Contains(item))
{
itemsToAdd.Add(item);
}
}
var type = selectedItems.GetType().GenericTypeArguments[0];
foreach (var item in itemsToAdd)
{
if (item == itemsToAdd.Last())
{
//if this is the last item, turn notifications back on
SelectedItemsStatus.SetUpdating(SelectedItems, false);
}
try
{
if (type.IsAssignableFrom(item.GetType()))
{
selectedItems.Add(item);
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
finally
{
_isUpdatingSource = false;
}
}
}
}