using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using Wpf.Ui.Extend.Extensions; namespace Wpf.Ui.Extend.Controls; /// /// 多选树形视图控件。 /// public sealed class MultiTreeView : TreeView { // public static readonly DependencyPropertyKey SelectedItemsPropertyKey = // DependencyProperty.RegisterReadOnly( //nameof(SelectedItems), // typeof(IList), // typeof(MultiTreeViewItem), // new FrameworkPropertyMetadata(null) // ); // public static readonly DependencyProperty SelectedItemsProperty = SelectedItemsPropertyKey.DependencyProperty; // public IList SelectedItems // { // get { return (IList)GetValue(SelectedItemsProperty); } // private set { SetValue(SelectedItemsPropertyKey, value); } // } public IList SelectedItems { get { return (IList)GetValue(SelectedItemsProperty); } set { SetValue(SelectedItemsProperty, value); } } public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(nameof(SelectedItems), typeof(IList), typeof(MultiTreeView), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedItemsChanged))); private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var list = e.NewValue as IList; //foreach (var item in list) //{ //} } #region Event Handlers /// /// 在鼠标按下事件发生时调用。 /// //protected override void OnPreviewMouseDown(MouseButtonEventArgs e) //{ // base.OnPreviewMouseDown(e); // //// 如果点击树分支expander // //if (e.OriginalSource is Grid or Border or TextBlock) // // return; // var obj = e.OriginalSource as DependencyObject; // var checkBox = obj.FindParent(); // if (checkBox != null) // { // //当前点击的MultiTreeViewItem // var currentItem = GetTreeViewItemClicked((FrameworkElement)e.OriginalSource); // if (currentItem != null) // { // SelectedItems = GetTreeViewItems(this, true).Where(d => d.IsChecked == true).ToList(); // } // } //} #endregion Event Handlers #region Utility Methods #region 重写 ///// ///// 准备项的容器 ///// ///// 控件元素 ///// 绑定的对象 //protected override void PrepareContainerForItemOverride(DependencyObject element, object item) //{ // if (item is not MultiTreeViewItem) // { // if (element is MultiTreeViewItem multiTreeViewItem && !string.IsNullOrEmpty(this.DisplayMemberPath)) // { // var binding = new Binding(this.DisplayMemberPath); // multiTreeViewItem.SetBinding(MultiTreeViewItem.HeaderProperty, binding); // } // } // base.PrepareContainerForItemOverride(element, item); //} /// /// 获取项的容器。 /// protected override DependencyObject GetContainerForItemOverride() { return new MultiTreeViewItem(); } /// /// 确定项是否是其自己的容器。 /// protected override bool IsItemItsOwnContainerOverride(object item) { return item is MultiTreeViewItem; } #endregion /// /// 获取当前被点击的MultiTreeViewItem。 /// private static MultiTreeViewItem GetTreeViewItemClicked(DependencyObject sender) { while (sender is not null and not MultiTreeViewItem) sender = VisualTreeHelper.GetParent(sender); return sender as MultiTreeViewItem; } /// /// 获取树形视图的所有展开的项。 /// private List GetTreeViewItems(ItemsControl parentItem, bool includeCollapsedItems, List itemList = null) { itemList ??= []; for (var index = 0; index < parentItem.Items.Count; index++) { if (parentItem.ItemContainerGenerator.ContainerFromIndex(index) is not MultiTreeViewItem tvItem) { continue; } itemList.Add(tvItem); if (includeCollapsedItems || tvItem.IsExpanded) { GetTreeViewItems(tvItem, includeCollapsedItems, itemList); } } return itemList; } internal void NotifyMultiTreeViewItemClicked(MultiTreeViewItem multiTreeViewItem) { var selectedItems = GetTreeViewItems(this, true).Where(d => d.IsChecked == true); if (ItemsSource==null) { SelectedItems = selectedItems.ToList(); } else { //选择绑定的对象 SelectedItems = selectedItems.Select(d => d.DataContext).ToList(); } } ///// ///// 获取两个树形视图项之间的所有项。 ///// //private List GetTreeViewItemRange(MultiTreeViewItem start, MultiTreeViewItem end) //{ // var items = GetTreeViewItems(this, false); // var startIndex = items.IndexOf(start); // var endIndex = items.IndexOf(end); // var rangeStart = startIndex > endIndex || startIndex == -1 ? endIndex : startIndex; // var rangeCount = startIndex > endIndex ? startIndex - endIndex + 1 : endIndex - startIndex + 1; // if (startIndex == -1 && endIndex == -1) // rangeCount = 0; // else if (startIndex == -1 || endIndex == -1) // rangeCount = 1; // return rangeCount > 0 ? items.GetRange(rangeStart, rangeCount) : new List(); //} #endregion Utility Methods static MultiTreeView() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiTreeView), new FrameworkPropertyMetadata(typeof(MultiTreeView))); } /// /// 初始化 MultiTreeView 类的新实例。 /// //public MultiTreeView() //{ //SelectedItemChanged += (sender, e) => //{ // if (e.NewValue is MultiTreeViewItem item) // SelectedItemChangedInternal(item); //}; //} }