2021-09-20 18:20:01 +02:00

153 lines
4.9 KiB
C#

/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
namespace dnSpy.Contracts.Controls.ToolWindows {
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public sealed class ListBoxSelectedItemsAP {
public static readonly DependencyProperty SelectedItemsVMProperty = DependencyProperty.RegisterAttached(
"SelectedItemsVM", typeof(IList), typeof(ListBoxSelectedItemsAP), new UIPropertyMetadata(null, SelectedItemsVMPropertyChangedCallback));
static readonly DependencyProperty InstanceProperty = DependencyProperty.RegisterAttached(
"Instance", typeof(ListBoxSelectedItemsAP), typeof(ListBoxSelectedItemsAP), new UIPropertyMetadata(null));
public static void SetSelectedItemsVM(ListBox listBox, IList value) =>
listBox.SetValue(SelectedItemsVMProperty, value);
public static IList GetSelectedItemsVM(ListBox listBox) =>
(IList)listBox.GetValue(SelectedItemsVMProperty);
static void SelectedItemsVMPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var lb = d as ListBox;
if (lb is null)
return;
var vmColl = e.NewValue as IList;
if (vmColl is null)
return;
var ncc = vmColl as INotifyCollectionChanged;
if (ncc is null)
return;
var inst = lb.GetValue(InstanceProperty) as ListBoxSelectedItemsAP;
if (inst is null)
lb.SetValue(InstanceProperty, inst = new ListBoxSelectedItemsAP());
inst.Initialize(lb, vmColl, ncc);
}
ListBox? listBox;
IList? vmColl;
INotifyCollectionChanged? vmCollNcc;
void Initialize(ListBox listBox, IList vmColl, INotifyCollectionChanged vmCollNcc) {
UnregisterEvents();
this.listBox = listBox;
this.vmColl = vmColl;
this.vmCollNcc = vmCollNcc;
vmColl.Clear();
foreach (var item in listBox.SelectedItems)
vmColl.Add(item);
RegisterEvents();
}
void UnregisterEvents() {
if (listBox is not null)
listBox.SelectionChanged -= ListBox_SelectionChanged;
if (vmCollNcc is not null)
vmCollNcc.CollectionChanged -= VmCollNcc_CollectionChanged;
}
void RegisterEvents() {
Debug2.Assert(listBox is not null);
Debug2.Assert(vmCollNcc is not null);
listBox.SelectionChanged += ListBox_SelectionChanged;
vmCollNcc.CollectionChanged += VmCollNcc_CollectionChanged;
}
void ListBox_SelectionChanged(object? sender, SelectionChangedEventArgs e) {
Debug2.Assert(listBox is not null);
Debug2.Assert(vmColl is not null);
if (ListBox_SelectionChanged_ignoreCalls)
return;
try {
VmCollNcc_CollectionChanged_ignoreCalls = true;
if (e.AddedItems is not null) {
foreach (var vmItem in e.AddedItems)
vmColl.Add(vmItem);
}
if (e.RemovedItems is not null) {
foreach (var vmItem in e.RemovedItems)
vmColl.Remove(vmItem);
}
}
finally {
VmCollNcc_CollectionChanged_ignoreCalls = false;
}
}
bool ListBox_SelectionChanged_ignoreCalls;
bool VmCollNcc_CollectionChanged_ignoreCalls;
void VmCollNcc_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) {
Debug2.Assert(listBox is not null);
if (VmCollNcc_CollectionChanged_ignoreCalls)
return;
try {
ListBox_SelectionChanged_ignoreCalls = true;
switch (e.Action) {
case NotifyCollectionChangedAction.Add:
Debug2.Assert(e.NewItems is not null);
if (e.NewItems is not null) {
foreach (var item in e.NewItems)
listBox.SelectedItems.Add(item);
}
break;
case NotifyCollectionChangedAction.Remove:
Debug2.Assert(e.OldItems is not null);
if (e.OldItems is not null) {
foreach (var item in e.OldItems)
listBox.SelectedItems.Remove(item);
}
break;
case NotifyCollectionChangedAction.Reset:
listBox.SelectedItems.Clear();
if (e.NewItems is not null) {
foreach (var item in e.NewItems)
listBox.SelectedItems.Add(item);
}
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move:
default:
throw new InvalidOperationException();
}
}
finally {
ListBox_SelectionChanged_ignoreCalls = false;
}
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}