using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using PropertyMetadata = System.Windows.PropertyMetadata; namespace YY.Admin.Core.Behavior { public class TreeViewItemClickBehavior { // ICommand attached property public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached( "Command", typeof(ICommand), typeof(TreeViewItemClickBehavior), new PropertyMetadata(null, OnCommandChanged)); public static void SetCommand(DependencyObject obj, ICommand value) => obj.SetValue(CommandProperty, value); public static ICommand GetCommand(DependencyObject obj) => (ICommand)obj.GetValue(CommandProperty); // CommandParameter attached property public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached( "CommandParameter", typeof(object), typeof(TreeViewItemClickBehavior), new PropertyMetadata(null)); public static void SetCommandParameter(DependencyObject obj, object value) => obj.SetValue(CommandParameterProperty, value); public static object GetCommandParameter(DependencyObject obj) => obj.GetValue(CommandParameterProperty); private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is TreeViewItem tvi) { if (e.NewValue != null && e.OldValue == null) { tvi.PreviewMouseLeftButtonUp += OnTreeViewItemMouseLeftButtonUp; // 监听 TreeViewItem 展开事件Expanded tvi.Expanded += OnTreeViewItemExpanded; } else if (e.NewValue == null && e.OldValue != null) { tvi.PreviewMouseLeftButtonUp -= OnTreeViewItemMouseLeftButtonUp; tvi.Expanded -= OnTreeViewItemExpanded; } } else { // 如果Style被应用到容器等,也可能不是TreeViewItem,延迟订阅由容器化过程处理 // 一般我们只使用在 TreeViewItem 上设置 } } private static void OnTreeViewItemMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // 忽略点击展开按钮 if (e.OriginalSource is DependencyObject dep) { if (FindAncestor(dep) != null) return; // 找到真正的 TreeViewItem var tvi = FindAncestor(dep); if (tvi == null) return; var cmd = GetCommand(tvi); var param = GetCommandParameter(tvi) ?? tvi.DataContext; // 检查是否有子项 bool hasChildren = tvi.HasItems; // 如果有子项,则切换展开状态 if (hasChildren) { bool IsExpanded = !tvi.IsExpanded; tvi.IsExpanded = IsExpanded; // 展开 //if (IsExpanded) //{ // // 关闭同级其它节点 // CollapseSiblings(tvi); //} e.Handled = true; return; } if (cmd != null && cmd.CanExecute(param)) { cmd.Execute(param); e.Handled = true; } } } private static void OnTreeViewItemExpanded(object sender, RoutedEventArgs e) { if (sender is TreeViewItem tvi) { // 防止事件冒泡重复执行 if (e.OriginalSource != tvi) return; CollapseSiblings(tvi); } } /// /// 折叠同级其它 TreeViewItem /// private static void CollapseSiblings(TreeViewItem currentItem) { ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(currentItem); if (parent == null) return; foreach (var item in parent.Items) { var container = parent.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; if (container != null && container != currentItem) { container.IsExpanded = false; } } } // 查找祖先辅助方法 private static T FindAncestor(DependencyObject current) where T : DependencyObject { while (current != null) { if (current is T t) return t; current = VisualTreeHelper.GetParent(current); } return null; } } }