使用附加依赖项属性搞定
public class TreeViewExtensions : TreeView
{
/// <summary>
/// Gets the value of the dependency property \"EnableMultiSelect\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <returns></returns>
public static bool GetEnableMultiSelect(Dependency obj)
{
return (bool)obj.GetValue(EnableMultiSelectProperty);
}
/// <summary>
/// Sets the value of the dependency property \"EnableMultiSelect\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <param name=\"value\"></param>
public static void SetEnableMultiSelect(Dependency 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 workProperty data(false)
{
PropertyChangedCallback = EnableMultiSelectChanged,
BindsTwoWayByDefault = true
});
/// <summary>
/// Gets the value of the dependency property \"SelectedItems\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <returns></returns>
public static IList GetSelectedItems(Dependency obj)
{
return (IList)obj.GetValue(SelectedItemsProperty);
}
/// <summary>
/// Sets the value of the dependency property \"SelectedItems\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <param name=\"value\"></param>
public static void SetSelectedItems(Dependency obj, IList value)
{
obj.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 Property data(null));
/// <summary>
/// Gets the value of the dependency property \"AnchorItem\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <returns></returns>
static TreeViewItem GetAnchorItem(Dependency obj)
{
return (TreeViewItem)obj.GetValue(AnchorItemProperty);
}
/// <summary>
/// Sets the value of the dependency property \"AnchorItem\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <param name=\"value\"></param>
static void SetAnchorItem(Dependency 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 Property data(null));
/// <summary>
/// Gets the value of the dependency property \"IsSelected\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <returns></returns>
public static bool GetIsSelected(Dependency obj)
{
return (bool)obj.GetValue(IsSelectedProperty);
}
/// <summary>
/// Sets the value of the dependency property \"IsSelected\".
/// </summary>
/// <param name=\"obj\">Dependency </param>
/// <param name=\"value\"></param>
public static void SetIsSelected(Dependency obj, bool value)
{
if (value)
{
GradientStopCollection gradientStopCollection = new GradientStopCollection();
gradientStopCollection.Add(new GradientStop()
{
Color = (Color)ColorConverter.ConvertFromString(\"#FF303030\"),
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
{
(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 Property data(false)
{
PropertyChangedCallback = RealSelectedChanged
});
/// <summary>
/// \"EnableMultiSelect\" changed event.
/// </summary>
/// <param name=\"s\">Dependency </param>
/// <param name=\"args\">Event parameter</param>
static void EnableMultiSelectChanged(Dependency 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));
}
}
/// <summary>
/// Gets TreeView which contains the TreeViewItem.
/// </summary>
/// <param name=\"item\">item</param>
/// <returns>TreeView</returns>
static TreeView GetTree(TreeViewItem item)
{
Func<Dependency , Dependency > getParent = (o) => VisualTreeHelper.GetParent(o);
workElement currentItem = item;
while (!(getParent(currentItem) is TreeView))
{
currentItem = ( workElement)getParent(currentItem);
}
return (TreeView)getParent(currentItem);
}
/// <summary>
/// TreeViewItem seleted changed event.
/// </summary>
/// <param name=\"sender\">sender</param>
/// <param name=\"args\">event parameter</param>
static void RealSelectedChanged(Dependency 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);
}
}
}
/// <summary>
/// Key down event.
/// </summary>
/// <param name=\"sender\">sender</param>
/// <param name=\"e\">event parameter</param>
static void KeyDown( 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);
}
e.Handled = true;
}
}
/// <summary>
/// Item clicked event.
/// </summary>
/// <param name=\"sender\">sender</param>
/// <param name=\"e\">event parameter</param>
static void ItemClicked( 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);
return;
}
}
/// <summary>
/// Find TreeViewItem which contains the .
/// </summary>
/// <param name=\"obj\">obj</param>
/// <returns></returns>
private static TreeViewItem FindTreeViewItem( obj)
{
Dependency dpObj = obj as Dependency ;
if (dpObj == null)
{
return null;
}
if (dpObj is TreeViewItem)
{
return (TreeViewItem)dpObj;
}
return FindTreeViewItem(VisualTreeHelper.GetParent(dpObj));
}
/// <summary>
/// Gets all expanded TreeViewItems.
/// </summary>
/// <param name=\"tree\">TreeView</param>
/// <returns></returns>
private static IEnumerable<TreeViewItem> 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;
}
// }
}
}
/// <summary>
/// Select by Shift key.
/// </summary>
/// <param name=\"tree\"></param>
/// <param name=\"actionItem\"></param>
/// <param name=\"clearCurrent\"></param>
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);
}
else
{
if (clearCurrent)
{
SetIsSelected(item, false);
}
else
{
break;
}
}
}
}
/// <summary>
/// Gets all selected TreeViewItems.
/// </summary>
/// <param name=\"tree\">TreeView</param>
/// <returns></returns>
private static List<TreeViewItem> GetSelectedTreeViewItems(TreeView tree)
{
return GetExpandedTreeViewItems(tree).Where(i => GetIsSelected(i)).ToList();
}
/// <summary>
/// Select by left mouse button.
/// </summary>
/// <param name=\"tree\"></param>
/// <param name=\"item\"></param>
private static void MakeSingleSelection(TreeView tree, TreeViewItem item)
{
foreach (TreeViewItem selectedItem in GetExpandedTreeViewItems(tree))
{
if (selectedItem == null)
{
continue;
}
if (selectedItem != item)
{
SetIsSelected(selectedItem, false);
}
else
{
SetIsSelected(selectedItem, true);
}
}
UpdateAnchorAndActionItem(tree, item);
}
/// <summary>
/// Select by Ctrl key.
/// </summary>
/// <param name=\"tree\">TreeView</param>
/// <param name=\"item\">TreeViewItem</param>
private static void MakeToggleSelection(TreeView tree, TreeViewItem item)
{
SetIsSelected(item, !GetIsSelected(item));
UpdateAnchorAndActionItem(tree, item);
}
/// <summary>
/// Update the Anchor TreeViewItem.
/// </summary>
/// <param name=\"tree\">TreeView</param>
/// <param name=\"item\">TreeViewItem</param>
private static void UpdateAnchorAndActionItem(TreeView tree, TreeViewItem item)
{
SetAnchorItem(tree, item);
}
}
继续阅读与本文标签相同的文章
上一篇 :
Excel–如何将数字转换为小写中文和大写中文?
下一篇 :
2招批量清除Excel中的空格字符
-
Win10启用使用Sandbox
2026-05-18栏目: 教程
-
草图大师怎么垂直旋转?su软件垂直旋转模型的方法
2026-05-18栏目: 教程
-
数字技术让“诗和远方”融为一体
2026-05-18栏目: 教程
-
“成人网站”免费让人上钩,其背后有什么不为人知的猫腻,网友:不敢惹
2026-05-18栏目: 教程
-
网络互连技术之路由协议
2026-05-18栏目: 教程
