功能更新
This commit is contained in:
162
Melskin/Controls/TreeGrid.xaml.cs
Normal file
162
Melskin/Controls/TreeGrid.xaml.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Melskin.Controls
|
||||
{
|
||||
// 定义模板中必须存在的部件,这是良好的自定义控件开发实践
|
||||
/// <summary>
|
||||
/// TreeGrid 控件是一个自定义控件,它结合了树形结构和表格布局的功能。通过此控件,用户可以展示具有层次结构的数据,并且能够以类似于表格的方式组织列。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该控件支持数据绑定、列定义以及行模板的自定义,允许灵活地展示复杂的数据结构。TreeGrid 内部使用了 ScrollViewer 和 TreeView 作为其主要组成部分来实现滚动和树形视图功能。
|
||||
/// </remarks>
|
||||
[TemplatePart(Name = "PART_HeaderScrollViewer", Type = typeof(ScrollViewer))]
|
||||
[TemplatePart(Name = "PART_ContentTreeView", Type = typeof(TreeView))]
|
||||
public class TreeGrid : Control
|
||||
{
|
||||
private ScrollViewer? headerScrollViewer;
|
||||
private ScrollViewer? contentScrollViewer;
|
||||
private TreeView? contentTreeView;
|
||||
|
||||
#region Dependency Properties
|
||||
|
||||
// 1. ItemsSource (IEnumerable) - 用于绑定数据源
|
||||
/// <summary>
|
||||
/// 表示 TreeGrid 控件的数据源的依赖属性,用于绑定到一个实现了 IEnumerable 接口的数据集合。
|
||||
/// 通过设置此属性,可以将具有层次结构或简单列表形式的数据绑定到控件上,从而在 TreeGrid 中展示数据。支持任何类型的数据源,只要它能够被枚举。
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemsSourceProperty =
|
||||
DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable), typeof(TreeGrid), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable ItemsSource
|
||||
{
|
||||
get => (IEnumerable)GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
// 2. Columns (GridViewColumnCollection) - 直接使用WPF内置的列集合
|
||||
/// <summary>
|
||||
/// 表示 TreeGrid 控件中定义的列集合的依赖属性,用于指定显示在控件中的各个列及其属性。
|
||||
/// 通过此属性可以添加、删除或修改列,例如设置列标题、绑定数据成员等。每个列都由一个 GridViewColumn 对象表示。
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ColumnsProperty =
|
||||
DependencyProperty.Register(nameof(Columns), typeof(GridViewColumnCollection), typeof(TreeGrid), new PropertyMetadata(new GridViewColumnCollection()));
|
||||
|
||||
/// <summary>
|
||||
/// 表示 TreeGrid 控件中定义的列集合,用于指定显示在控件中的各个列及其属性。
|
||||
/// 通过此属性可以添加、删除或修改列,例如设置列标题、绑定数据成员等。每个列都由一个 GridViewColumn 对象表示。
|
||||
/// </summary>
|
||||
public GridViewColumnCollection Columns
|
||||
{
|
||||
get => (GridViewColumnCollection)GetValue(ColumnsProperty);
|
||||
set => SetValue(ColumnsProperty, value);
|
||||
}
|
||||
|
||||
// 3. ItemTemplate (HierarchicalDataTemplate) - 用户自定义行和子项的模板
|
||||
/// <summary>
|
||||
/// 表示用于设置或获取 TreeGrid 控件中每个项的数据模板的依赖属性。
|
||||
/// 通过此属性,用户可以自定义 TreeViewItem 的数据展示方式,例如通过 HierarchicalDataTemplate 定义复杂的数据结构展示。
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemTemplateProperty =
|
||||
DependencyProperty.Register(nameof(ItemTemplate), typeof(HierarchicalDataTemplate), typeof(TreeGrid), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public HierarchicalDataTemplate ItemTemplate
|
||||
{
|
||||
get => (HierarchicalDataTemplate)GetValue(ItemTemplateProperty);
|
||||
set => SetValue(ItemTemplateProperty, value);
|
||||
}
|
||||
|
||||
// 4. ItemContainerStyle (Style) - 允许用户自定义 TreeViewItem 的样式
|
||||
/// <summary>
|
||||
/// 表示用于设置或获取 TreeGrid 控件中每个项的容器样式(即 TreeViewItem 的样式)的依赖属性。
|
||||
/// 通过此属性,用户可以自定义 TreeViewItem 的外观,例如修改其背景色、边框样式等视觉效果。
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemContainerStyleProperty =
|
||||
DependencyProperty.Register(nameof(ItemContainerStyle), typeof(Style), typeof(TreeGrid), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置应用于 TreeGrid 控件中每个项容器(即 TreeViewItem)的样式。
|
||||
/// 通过此属性,可以自定义 TreeViewItem 的外观,例如背景色、边框样式等视觉效果。
|
||||
/// </summary>
|
||||
public Style ItemContainerStyle
|
||||
{
|
||||
get => (Style)GetValue(ItemContainerStyleProperty);
|
||||
set => SetValue(ItemContainerStyleProperty, value);
|
||||
}
|
||||
|
||||
// 也可以添加 SelectedItem, CornerRadius 等其他 BUI 库中有的属性...
|
||||
|
||||
#endregion
|
||||
|
||||
static TreeGrid()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGrid), new FrameworkPropertyMetadata(typeof(TreeGrid)));
|
||||
}
|
||||
|
||||
// 当控件的模板应用时,此方法被调用
|
||||
/// <inheritdoc />
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
// 解除旧的事件处理器,防止内存泄漏
|
||||
if (contentScrollViewer != null)
|
||||
contentScrollViewer.ScrollChanged -= OnContentScrollChanged;
|
||||
|
||||
// 从模板中获取关键部件
|
||||
headerScrollViewer = GetTemplateChild("PART_HeaderScrollViewer") as ScrollViewer;
|
||||
contentTreeView = GetTemplateChild("PART_ContentTreeView") as TreeView;
|
||||
|
||||
if (contentTreeView != null)
|
||||
{
|
||||
// TreeView 加载完成后,查找其内部的 ScrollViewer
|
||||
contentTreeView.Loaded += (_, _) =>
|
||||
{
|
||||
contentScrollViewer = FindVisualChild<ScrollViewer>(contentTreeView);
|
||||
|
||||
if (contentScrollViewer != null)
|
||||
{
|
||||
// 【核心】挂载滚动同步事件
|
||||
contentScrollViewer.ScrollChanged += OnContentScrollChanged;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 当内容滚动时,同步表头的水平滚动位置
|
||||
private void OnContentScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if (headerScrollViewer != null && e.HorizontalChange != 0)
|
||||
{
|
||||
headerScrollViewer.ScrollToHorizontalOffset(e.HorizontalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:在可视化树中查找指定类型的子元素
|
||||
private static T? FindVisualChild<T>(DependencyObject? obj) where T : DependencyObject
|
||||
{
|
||||
if (obj == null) return null;
|
||||
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T typedChild)
|
||||
{
|
||||
return typedChild;
|
||||
}
|
||||
|
||||
T? childOfChild = FindVisualChild<T>(child);
|
||||
if (childOfChild != null)
|
||||
{
|
||||
return childOfChild;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user