using Microsoft.Xaml.Behaviors; using System.Collections; using System.Collections.Specialized; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; namespace Szmedi.RvKits.Behaviors; //public class MyObjectListBoxSelectionBehavior : ListBoxSelectionBehavior //{ //} // // // internal class SelectedItemsBehavior : Behavior { // Using a DependencyProperty as the backing store for BindableSelectedItems. This enables animation, styling, binding, etc... public static readonly DependencyProperty BindableSelectedItemsProperty = DependencyProperty.Register( nameof(BindableSelectedItems), typeof(IList), typeof(SelectedItemsBehavior), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged)); public static readonly DependencyProperty BindableSelectedValuesProperty = DependencyProperty.Register( nameof(BindableSelectedValues), typeof(IList), typeof(SelectedItemsBehavior), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged ) ); private bool modelHandled; private bool viewHandled; public IList BindableSelectedItems { get => (IList)GetValue(BindableSelectedItemsProperty); set => SetValue(BindableSelectedItemsProperty, value); } protected override void OnAttached() { base.OnAttached(); AssociatedObject.SelectionChanged += OnSelectionChanged; ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += OnItemsChanged; } protected override void OnDetaching() { base.OnDetaching(); if (AssociatedObject != null) { AssociatedObject.SelectionChanged -= OnSelectionChanged; ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged -= OnItemsChanged; } } // Propagate selected items from view to model private void SelectItems() { viewHandled = true; AssociatedObject.SelectedItems.Clear(); if (BindableSelectedItems != null) { foreach (var item in BindableSelectedItems) { AssociatedObject.SelectedItems.Add(item); } } viewHandled = false; } private static void OnSelectedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { var behavior = (SelectedItemsBehavior)sender; if (behavior.modelHandled) { return; } if (behavior.AssociatedObject == null) { return; } behavior.modelHandled = true; behavior.SelectItems(); behavior.modelHandled = false; } // Re-select items when the set of items changes private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs args) { if (viewHandled) { return; } if (AssociatedObject.Items.SourceCollection == null) { return; } SelectItems(); } private void OnSelectionChanged(object sender, SelectionChangedEventArgs args) { if (viewHandled) { return; } if (AssociatedObject.Items.SourceCollection == null) { return; } BindableSelectedItems = AssociatedObject.SelectedItems.Cast().ToArray(); } private static object GetDeepPropertyValue(object obj, string path) { if (string.IsNullOrWhiteSpace(path)) { return obj; } while (true) { if (path.Contains('.')) { string[] split = path.Split('.'); string remainingProperty = path.Substring(path.IndexOf('.') + 1); obj = obj.GetType().GetProperty(split[0]).GetValue(obj, null); path = remainingProperty; continue; } return obj.GetType().GetProperty(path).GetValue(obj, null); } } public IList BindableSelectedValues { get => (IList)GetValue(BindableSelectedValuesProperty); set => SetValue(BindableSelectedValuesProperty, value); } // Update SelectedItems based on SelectedValues private void SelectedValuesToItems() { BindableSelectedItems = BindableSelectedValues == null ? null : (IList)AssociatedObject.Items.Cast() .Where(i => BindableSelectedValues.Contains(GetDeepPropertyValue(i, AssociatedObject.SelectedValuePath))) .ToArray(); } // Update SelectedValues based on SelectedItems private void SelectedItemsToValues() { BindableSelectedValues = BindableSelectedItems == null ? null : (IList)BindableSelectedItems.Cast() .Select(i => GetDeepPropertyValue(i, AssociatedObject.SelectedValuePath)) .ToArray(); } //private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) //{ // var selector = (MultiSelector)sender; // BindableSelectedItems = selector.BindableSelectedItems; // selector.GetBindingExpression(BindableSelectedItemsProperty)?.UpdateSource(); //} //public static IList GetBindableSelectedItems(DependencyObject obj) //{ // return (IList)obj.GetValue(BindableSelectedItemsProperty); //} //public static void SetBindableSelectedItems(DependencyObject obj, IList value) //{ // obj.SetValue(BindableSelectedItemsProperty, value); //} //// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... //public static readonly DependencyProperty BindableSelectedItemsProperty = // DependencyProperty.RegisterAttached("BindableSelectedItems", typeof(IList), typeof(SelectedItemsBehavior), new PropertyMetadata(null)); }