From daf83c4bbcd8e218f4a871d5ebc3ee6bba350c73 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Wed, 3 Jul 2024 12:25:07 +0200 Subject: [PATCH] CheckComboBox: Add setter for SelectedItems --- Elwig/Controls/CheckComboBox.cs | 68 ++++++++++++++++++-- Elwig/Controls/WineOriginTemplateSelector.cs | 2 +- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Elwig/Controls/CheckComboBox.cs b/Elwig/Controls/CheckComboBox.cs index b4dc86d..a66864f 100644 --- a/Elwig/Controls/CheckComboBox.cs +++ b/Elwig/Controls/CheckComboBox.cs @@ -1,10 +1,19 @@ -using System.Linq; +using System.Collections; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; using System.Windows; using System.Windows.Controls; namespace Elwig.Controls { public class CheckComboBox : ListBox { + public new static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(nameof(SelectedItems), typeof(IList), typeof(CheckComboBox), new FrameworkPropertyMetadata(new ObservableCollection(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChangedCallback)); + public new IList SelectedItems { + get => (IList)GetValue(SelectedItemsProperty); + set => SetValue(SelectedItemsProperty, value); + } + public static readonly DependencyProperty DelimiterProperty = DependencyProperty.Register(nameof(Delimiter), typeof(string), typeof(CheckComboBox), new FrameworkPropertyMetadata(", ")); public string Delimiter { get => (string)GetValue(DelimiterProperty); @@ -47,27 +56,50 @@ namespace Elwig.Controls { set => SetValue(MaxDropDownHeightProperty, value); } + public new static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent(nameof(SelectionChanged), RoutingStrategy.Bubble, typeof(SelectionChangedEventHandler), typeof(CheckComboBox)); + public new event SelectionChangedEventHandler SelectionChanged { + add => AddHandler(SelectionChangedEvent, value); + remove => RemoveHandler(SelectionChangedEvent, value); + } + static CheckComboBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckComboBox), new FrameworkPropertyMetadata(typeof(CheckComboBox))); } - private TextBlock TextBox; + private bool _viewHandled; + private bool _modelHandled; + private TextBlock _textBox; public CheckComboBox() { SelectionMode = SelectionMode.Multiple; } public override void OnApplyTemplate() { - TextBox = (GetTemplateChild("TextBox") as TextBlock)!; + _textBox = (GetTemplateChild("TextBox") as TextBlock)!; var button = GetTemplateChild("Button") as Button; button!.Click += Button_MouseDown; var item = GetTemplateChild("SelectAllItem") as ListBoxItem; item!.PreviewMouseDown += SelectAllItem_MouseDown; - SelectionChanged += OnSelectionChanged; + if (SelectedItems is INotifyCollectionChanged collection) { + collection.CollectionChanged += (s, e) => { SelectItems(); }; + } IsEnabledChanged += OnIsEnabledChanged; + base.SelectionChanged += OnSelectionChanged; base.OnApplyTemplate(); } + private static void OnSelectedItemsChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e) { + if (sender is CheckComboBox ccb) + ccb.OnSelectedItemsChanged(); + } + + private void OnSelectedItemsChanged() { + if (SelectedItems is INotifyCollectionChanged collection) { + collection.CollectionChanged += (s, e) => { SelectItems(); }; + } + SelectItems(); + } + private void Button_MouseDown(object sender, RoutedEventArgs evt) { IsDropDownOpen = !IsDropDownOpen; } @@ -82,25 +114,47 @@ namespace Elwig.Controls { } private void OnSelectionChanged(object sender, SelectionChangedEventArgs evt) { + SelectItemsReverse(); var dmp = DisplayMemberPath != null && DisplayMemberPath != "" ? DisplayMemberPath : null; if (SelectedItems.Count == ItemsSource.Cast().Count() && AllItemsSelectedContent != null) { - TextBox.Text = AllItemsSelectedContent; + _textBox.Text = AllItemsSelectedContent; AllItemsSelected = true; } else if (SelectedItems.Count == 0) { - TextBox.Text = ""; + _textBox.Text = ""; AllItemsSelected = false; } else { - TextBox.Text = string.Join(Delimiter, + _textBox.Text = string.Join(Delimiter, dmp == null ? SelectedItems.Cast() : SelectedItems.Cast() .Select(i => i.GetType().GetProperty(dmp)?.GetValue(i)) ); AllItemsSelected = null; } + RaiseEvent(new SelectionChangedEventArgs(SelectionChangedEvent, evt.RemovedItems, evt.AddedItems)); } private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs evt) { if (!IsEnabled) IsDropDownOpen = false; } + + private void SelectItems() { + if (_viewHandled || _modelHandled) + return; + _viewHandled = true; + base.SelectedItems.Clear(); + foreach (var item in SelectedItems) + base.SelectedItems.Add(item); + _viewHandled = false; + } + + private void SelectItemsReverse() { + if (_modelHandled || _viewHandled) + return; + _modelHandled = true; + SelectedItems.Clear(); + foreach (var item in base.SelectedItems) + SelectedItems.Add(item); + _modelHandled = false; + } } } diff --git a/Elwig/Controls/WineOriginTemplateSelector.cs b/Elwig/Controls/WineOriginTemplateSelector.cs index f350ca2..7bad4bc 100644 --- a/Elwig/Controls/WineOriginTemplateSelector.cs +++ b/Elwig/Controls/WineOriginTemplateSelector.cs @@ -12,4 +12,4 @@ namespace Elwig.Controls { } } } -} \ No newline at end of file +}