Transfer.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Input;
  9. using HandyControl.Collections;
  10. using HandyControl.Data;
  11. using HandyControl.Interactivity;
  12. namespace HandyControl.Controls;
  13. [TemplatePart(Name = ElementSelectedListBox, Type = typeof(ListBox))]
  14. [DefaultEvent(nameof(TransferredItemsChanged))]
  15. public class Transfer : ListBox
  16. {
  17. private const string ElementSelectedListBox = "PART_SelectedListBox";
  18. public static readonly RoutedEvent TransferredItemsChangedEvent =
  19. EventManager.RegisterRoutedEvent("TransferredItemsChanged", RoutingStrategy.Bubble,
  20. typeof(SelectionChangedEventHandler), typeof(Transfer));
  21. [Category("Behavior")]
  22. public event SelectionChangedEventHandler TransferredItemsChanged
  23. {
  24. add => AddHandler(TransferredItemsChangedEvent, value);
  25. remove => RemoveHandler(TransferredItemsChangedEvent, value);
  26. }
  27. private ListBox _selectedListBox;
  28. private static readonly DependencyPropertyKey TransferredItemsPropertyKey =
  29. DependencyProperty.RegisterReadOnly("TransferredItems", typeof(IList),
  30. typeof(Transfer), new FrameworkPropertyMetadata((IList) null));
  31. private static readonly DependencyProperty TransferredItemsImplProperty =
  32. TransferredItemsPropertyKey.DependencyProperty;
  33. [Bindable(true), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  34. public IList TransferredItems => TransferredItemsImpl;
  35. private IList TransferredItemsImpl => (IList) GetValue(TransferredItemsImplProperty);
  36. public Transfer()
  37. {
  38. CommandBindings.Add(new CommandBinding(ControlCommands.Selected, SelectItems));
  39. CommandBindings.Add(new CommandBinding(ControlCommands.Cancel, DeselectItems));
  40. Loaded += OnLoaded;
  41. }
  42. private void OnLoaded(object sender, RoutedEventArgs e)
  43. {
  44. SelectItems(null, null);
  45. }
  46. public override void OnApplyTemplate()
  47. {
  48. base.OnApplyTemplate();
  49. _selectedListBox = GetTemplateChild(ElementSelectedListBox) as ListBox;
  50. }
  51. protected virtual void OnTransferredItemsChanged(SelectionChangedEventArgs e)
  52. {
  53. RaiseEvent(e);
  54. }
  55. protected override bool IsItemItsOwnContainerOverride(object item) => item is TransferItem;
  56. protected override DependencyObject GetContainerForItemOverride() => new TransferItem();
  57. private void SelectItems(object sender, ExecutedRoutedEventArgs e)
  58. {
  59. if (_selectedListBox == null || SelectedItems.Count == 0)
  60. {
  61. return;
  62. }
  63. foreach (var item in SelectedItems)
  64. {
  65. if (ItemContainerGenerator.ContainerFromItem(item) is not TransferItem { IsTransferred: false } selectedItem)
  66. {
  67. continue;
  68. }
  69. selectedItem.IsTransferred = true;
  70. var transferItem = new TransferItem
  71. {
  72. Tag = item
  73. };
  74. if (ItemsSource != null)
  75. {
  76. transferItem.SetBinding(ContentControl.ContentProperty, new Binding(DisplayMemberPath) { Source = item });
  77. }
  78. else
  79. {
  80. transferItem.Content = IsItemItsOwnContainerOverride(item) ? ((TransferItem) item).Content : item;
  81. }
  82. _selectedListBox.Items.Add(transferItem);
  83. }
  84. SetTransferredItems(_selectedListBox.Items.OfType<TransferItem>().Select(item => item.Tag));
  85. OnTransferredItemsChanged(new SelectionChangedEventArgs(TransferredItemsChangedEvent, new List<object>(), SelectedItems)
  86. {
  87. Source = this
  88. });
  89. UnselectAll();
  90. }
  91. private void DeselectItems(object sender, ExecutedRoutedEventArgs e)
  92. {
  93. if (_selectedListBox == null)
  94. {
  95. return;
  96. }
  97. var deselectItems = new List<object>();
  98. foreach (var transferItem in _selectedListBox.Items.OfType<TransferItem>().ToList())
  99. {
  100. if (!transferItem.IsSelected)
  101. {
  102. continue;
  103. }
  104. if (ItemContainerGenerator.ContainerFromItem(transferItem.Tag) is not TransferItem selectedItem)
  105. {
  106. continue;
  107. }
  108. _selectedListBox.Items.Remove(transferItem);
  109. deselectItems.Add(transferItem.Tag);
  110. selectedItem.SetCurrentValue(TransferItem.IsTransferredProperty, ValueBoxes.FalseBox);
  111. selectedItem.SetCurrentValue(ListBoxItem.IsSelectedProperty, ValueBoxes.FalseBox);
  112. }
  113. SetTransferredItems(_selectedListBox.Items.OfType<TransferItem>().Select(item => item.Tag));
  114. OnTransferredItemsChanged(new SelectionChangedEventArgs(TransferredItemsChangedEvent, deselectItems, new List<object>())
  115. {
  116. Source = this
  117. });
  118. }
  119. private void SetTransferredItems(IEnumerable selectedItems)
  120. {
  121. var oldSelectedItems = (ManualObservableCollection<object>) GetValue(TransferredItemsImplProperty);
  122. if (oldSelectedItems == null)
  123. {
  124. oldSelectedItems = new ManualObservableCollection<object>();
  125. SetValue(TransferredItemsPropertyKey, oldSelectedItems);
  126. }
  127. oldSelectedItems.CanNotify = false;
  128. oldSelectedItems.Clear();
  129. foreach (var selectedItem in selectedItems)
  130. {
  131. oldSelectedItems.Add(selectedItem);
  132. }
  133. oldSelectedItems.CanNotify = true;
  134. }
  135. }