using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.ComponentModel; using System.Collections; using System.Windows.Media; using XImagingXhandler.XDAL; using XHandler.View; namespace XHandler.Controls { public class TreeViewExtensions : DependencyObject { public static TestDesign testDesign; /// /// Gets the value of the dependency property "EnableMultiSelect". /// /// Dependency Object /// public static bool GetEnableMultiSelect(DependencyObject obj) { return (bool)obj.GetValue(EnableMultiSelectProperty); } /// /// Sets the value of the dependency property "EnableMultiSelect". /// /// Dependency Object /// public static void SetEnableMultiSelect(DependencyObject obj, bool value) { obj.SetValue(EnableMultiSelectProperty, value); } // Using a DependencyProperty as the backing store for EnableMultiSelect. This enables animation, styling, binding, etc... public static readonly DependencyProperty EnableMultiSelectProperty = DependencyProperty.RegisterAttached("EnableMultiSelect", typeof(bool), typeof(TreeViewExtensions), new FrameworkPropertyMetadata(false) { PropertyChangedCallback = EnableMultiSelectChanged, BindsTwoWayByDefault = true }); /// /// Gets the value of the dependency property "SelectedItems". /// /// Dependency Object /// public static IList GetSelectedItems(DependencyObject obj) { return (IList)obj.GetValue(SelectedItemsProperty); } /// /// Sets the value of the dependency property "SelectedItems". /// /// Dependency Object /// public static void SetSelectedItems(DependencyObject obj, IList value) { obj.SetValue(SelectedItemsProperty, value); } /// /// 已经选中的节点 /// public List SelectedItems { get { return (List)GetValue(SelectedItemsProperty); } set { SetValue(SelectedItemsProperty, value); } } // Using a DependencyProperty as the backing store for SelectedItems. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(TreeViewExtensions), new FrameworkPropertyMetadata(null) { PropertyChangedCallback = MultiSelectChanged, BindsTwoWayByDefault = true }); /// /// TreeViewItem seleted changed event. /// /// sender /// event parameter static void MultiSelectChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { TreeViewItem item = (TreeViewItem)sender; var selectedItems = GetSelectedItems(GetTree(item)); SetSelectedItems(item.Parent, selectedItems); } /// /// Gets the value of the dependency property "AnchorItem". /// /// Dependency Object /// static TreeViewItem GetAnchorItem(DependencyObject obj) { return (TreeViewItem)obj.GetValue(AnchorItemProperty); } /// /// Sets the value of the dependency property "AnchorItem". /// /// Dependency Object /// static void SetAnchorItem(DependencyObject obj, TreeViewItem value) { obj.SetValue(AnchorItemProperty, value); } // Using a DependencyProperty as the backing store for AnchorItem. This enables animation, styling, binding, etc... static readonly DependencyProperty AnchorItemProperty = DependencyProperty.RegisterAttached("AnchorItem", typeof(TreeViewItem), typeof(TreeViewExtensions), new PropertyMetadata(null)); /// /// Gets the value of the dependency property "IsSelected". /// /// Dependency Object /// public static bool GetIsSelected(DependencyObject obj) { return (bool)obj.GetValue(IsSelectedProperty); } private static MethodEx FindMethodExByIndex(MethodEx method, string indexName) { if (method.strIndex == indexName) return method; else { if (method.Children.Count > 0) { foreach (var m in method.Children) { MethodEx find = FindMethodExByIndex(m, indexName); if (find != null) return find; } } else return null; } return null; } /// /// Sets the value of the dependency property "IsSelected". /// /// Dependency Object /// public static void SetIsSelected(DependencyObject obj, bool value, int type = 0) { if (value) { if (type == 1) { ((TreeViewItem)obj).IsSelected = value; ((MethodEx)((TreeViewItem)obj).Header).isSelected = value; if (testDesign != null) { MethodEx methodEx = FindMethodExByIndex(testDesign.rootMethod, ((MethodEx)((TreeViewItem)obj).Header).strIndex); if (methodEx != null) methodEx.isSelected = value; } } GradientStopCollection gradientStopCollection = new GradientStopCollection(); gradientStopCollection.Add(new GradientStop() { Color = (Color)ColorConverter.ConvertFromString("#FFC7DFFC"), Offset = 1 }); gradientStopCollection.Add(new GradientStop() { Color = (Color)ColorConverter.ConvertFromString("#FF3832B8"), Offset = 1 }); LinearGradientBrush brush = new LinearGradientBrush(gradientStopCollection, new Point(0.5, 0), new Point(0.5, 1)); (obj as TreeViewItem).Background = brush; } else { if (type == 1) { ((TreeViewItem)obj).IsSelected = value; ((MethodEx)((TreeViewItem)obj).Header).isSelected = value; if (testDesign != null) { MethodEx methodEx = FindMethodExByIndex(testDesign.rootMethod, ((MethodEx)((TreeViewItem)obj).Header).strIndex); if (methodEx != null) methodEx.isSelected = value; } } (obj as TreeViewItem).Background = Brushes.Transparent; } obj.SetValue(IsSelectedProperty, value); } // Using a DependencyProperty as the backing store for IsSelected. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.RegisterAttached("IsSelected", typeof(bool), typeof(TreeViewExtensions), new FrameworkPropertyMetadata(false) { PropertyChangedCallback = RealSelectedChanged, BindsTwoWayByDefault = true }); /// /// "EnableMultiSelect" changed event. /// /// Dependency Object /// Event parameter static void EnableMultiSelectChanged(DependencyObject s, DependencyPropertyChangedEventArgs args) { TreeView tree = (TreeView)s; var wasEnable = (bool)args.OldValue; var isEnabled = (bool)args.NewValue; if (wasEnable) { tree.RemoveHandler(TreeViewItem.MouseDownEvent, new MouseButtonEventHandler(ItemClicked)); tree.RemoveHandler(TreeView.KeyDownEvent, new KeyEventHandler(KeyDown)); } if (isEnabled) { tree.AddHandler(TreeViewItem.MouseDownEvent, new MouseButtonEventHandler(ItemClicked), true); tree.AddHandler(TreeView.KeyDownEvent, new KeyEventHandler(KeyDown)); } } /// /// Gets TreeView which contains the TreeViewItem. /// /// item /// TreeView static TreeView GetTree(TreeViewItem item) { Func getParent = (o) => VisualTreeHelper.GetParent(o); FrameworkElement currentItem = item; while (!(getParent(currentItem) is TreeView)) { currentItem = (FrameworkElement)getParent(currentItem); } return (TreeView)getParent(currentItem); } /// /// TreeViewItem seleted changed event. /// /// sender /// event parameter static void RealSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { TreeViewItem item = (TreeViewItem)sender; var selectedItems = GetSelectedItems(GetTree(item)); if (selectedItems != null) { var isSelected = GetIsSelected(item); if (isSelected) { try { selectedItems.Add(item.Header); } catch (ArgumentException) { } } else { selectedItems.Remove(item.Header); } } } /// /// Key down event. /// /// sender /// event parameter static void KeyDown(object sender, KeyEventArgs e) { TreeView tree = (TreeView)sender; if (e.Key == Key.A && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { foreach (var item in GetExpandedTreeViewItems(tree)) { SetIsSelected(item, true,1); } e.Handled = true; } } /// /// Item clicked event. /// /// sender /// event parameter static void ItemClicked(object sender, MouseButtonEventArgs e) { TreeViewItem item = FindTreeViewItem(e.OriginalSource); if (item == null) { return; } TreeView tree = (TreeView)sender; var mouseButton = e.ChangedButton; if (mouseButton != MouseButton.Left) { if ((mouseButton == MouseButton.Right) && ((Keyboard.Modifiers & (ModifierKeys.Shift | ModifierKeys.Control)) == ModifierKeys.None)) { if (GetIsSelected(item)) { UpdateAnchorAndActionItem(tree, item); return; } MakeSingleSelection(tree, item); } return; } if ((Keyboard.Modifiers & (ModifierKeys.Shift | ModifierKeys.Control)) != (ModifierKeys.Shift | ModifierKeys.Control)) { if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { MakeToggleSelection(tree, item); return; } if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) { MakeAnchorSelection(tree, item, true); return; } MakeSingleSelection(tree, item); e.Handled = true; return; } } /// /// Find TreeViewItem which contains the object. /// /// obj /// private static TreeViewItem FindTreeViewItem(object obj) { DependencyObject dpObj = obj as DependencyObject; if (dpObj == null) { return null; } if (dpObj is TreeViewItem) { return (TreeViewItem)dpObj; } return FindTreeViewItem(VisualTreeHelper.GetParent(dpObj)); } /// /// Gets all expanded TreeViewItems. /// /// TreeView /// private static IEnumerable GetExpandedTreeViewItems(ItemsControl tree) { for (int i = 0; i < tree.Items.Count; i++) { var item = (TreeViewItem)tree.ItemContainerGenerator.ContainerFromIndex(i); if (item == null) { continue; } yield return item; if (item.IsExpanded) { foreach (var subItem in GetExpandedTreeViewItems(item)) { yield return subItem; } } } } /// /// Select by Shift key. /// /// /// /// private static void MakeAnchorSelection(TreeView tree, TreeViewItem actionItem, bool clearCurrent) { if (GetAnchorItem(tree) == null) { var selectedItems = GetSelectedTreeViewItems(tree); if (selectedItems.Count > 0) { SetAnchorItem(tree, selectedItems[selectedItems.Count - 1]); } else { SetAnchorItem(tree, GetExpandedTreeViewItems(tree).Skip(3).FirstOrDefault()); } if (GetAnchorItem(tree) == null) { return; } } var anchor = GetAnchorItem(tree); var items = GetExpandedTreeViewItems(tree); bool betweenBoundary = false; foreach (var item in items) { bool isBoundary = item == anchor || item == actionItem; if (isBoundary) { betweenBoundary = !betweenBoundary; } if (betweenBoundary || isBoundary) { SetIsSelected(item, true,1); } else { if (clearCurrent) { SetIsSelected(item, false,1); } else { break; } } } } /// /// Gets all selected TreeViewItems. /// /// TreeView /// private static List GetSelectedTreeViewItems(TreeView tree) { return GetExpandedTreeViewItems(tree).Where(i => GetIsSelected(i)).ToList(); } /// /// Select by left mouse button. /// /// /// private static void MakeSingleSelection(TreeView tree, TreeViewItem item) { foreach (TreeViewItem selectedItem in GetExpandedTreeViewItems(tree)) { if (selectedItem == null) { continue; } if (selectedItem != item) { SetIsSelected(selectedItem, false,1); } else { SetIsSelected(selectedItem, true,1); } } UpdateAnchorAndActionItem(tree, item); } /// /// Select by Ctrl key. /// /// TreeView /// TreeViewItem private static void MakeToggleSelection(TreeView tree, TreeViewItem item) { SetIsSelected(item, !GetIsSelected(item),1); UpdateAnchorAndActionItem(tree, item); } /// /// Update the Anchor TreeViewItem. /// /// TreeView /// TreeViewItem private static void UpdateAnchorAndActionItem(TreeView tree, TreeViewItem item) { SetAnchorItem(tree, item); } } }