添加项目文件。
This commit is contained in:
194
Szmedi.RvKits/Behaviors/SelectedItemsBehavior.cs
Normal file
194
Szmedi.RvKits/Behaviors/SelectedItemsBehavior.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
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<MyObject>
|
||||
//{
|
||||
//}
|
||||
// <i:Interaction.Behaviors>
|
||||
// <behaviors:MyObjectListBoxSelectionBehavior BindableSelectedItems = "{Binding SelectedItems}" BindableSelectedValues="{Binding SelectedValues}"/>
|
||||
// </ i:Interaction.Behaviors>
|
||||
internal class SelectedItemsBehavior<T> : Behavior<MultiSelector>
|
||||
{
|
||||
// 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<T>),
|
||||
new FrameworkPropertyMetadata(
|
||||
null,
|
||||
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||
OnSelectedItemsChanged));
|
||||
public static readonly DependencyProperty BindableSelectedValuesProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(BindableSelectedValues),
|
||||
typeof(IList),
|
||||
typeof(SelectedItemsBehavior<T>),
|
||||
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<T>)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<T>().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<T>()
|
||||
.Where(i => BindableSelectedValues.Contains(GetDeepPropertyValue(i, AssociatedObject.SelectedValuePath)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// Update SelectedValues based on SelectedItems
|
||||
private void SelectedItemsToValues()
|
||||
{
|
||||
BindableSelectedValues = BindableSelectedItems == null
|
||||
? null
|
||||
: (IList)BindableSelectedItems.Cast<T>()
|
||||
.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));
|
||||
}
|
||||
Reference in New Issue
Block a user