EPLAN_PROD_Plugin/Sinvo.EplanHpD.Plugin.WPFUI/Utils/ScrollSynchronizer.cs

202 lines
7.2 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Sinvo.EplanHpD.Plugin.WPFUI.Utils
{
public static class ScrollSynchronizer
{
// 附加属性定义
public static readonly DependencyProperty SynchronizeWithParentProperty =
DependencyProperty.RegisterAttached(
"SynchronizeWithParent",
typeof(bool),
typeof(ScrollSynchronizer),
new PropertyMetadata(false, OnSynchronizeWithParentChanged));
// 为 ListBox 添加自动寻找内部 DataGrid 的附加属性
public static readonly DependencyProperty AutoSynchronizeChildrenProperty =
DependencyProperty.RegisterAttached(
"AutoSynchronizeChildren",
typeof(bool),
typeof(ScrollSynchronizer),
new PropertyMetadata(false, OnAutoSynchronizeChildrenChanged));
// Getter 和 Setter
public static bool GetSynchronizeWithParent(DependencyObject obj)
{
return (bool)obj.GetValue(SynchronizeWithParentProperty);
}
public static void SetSynchronizeWithParent(DependencyObject obj, bool value)
{
obj.SetValue(SynchronizeWithParentProperty, value);
}
/// <summary>
/// 当属性值改变时触发
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void OnSynchronizeWithParentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UIElement element)
{
if ((bool)e.NewValue)
{
// 添加事件处理
element.PreviewMouseWheel += Element_PreviewMouseWheel;
}
else
{
// 移除事件处理
element.PreviewMouseWheel -= Element_PreviewMouseWheel;
}
}
}
/// <summary>
/// 处理滚动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Element_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (sender is UIElement element)
{
// 向上查找父级 ListBox
var listBox = FindParentListBox(element);
if (listBox != null)
{
// 直接获取 ListBox 的 ScrollViewer
ScrollViewer scrollViewer = GetScrollViewer(listBox);
if (scrollViewer != null)
{
// 直接控制滚动位置
if (e.Delta < 0)
{
scrollViewer.LineDown();
}
else
{
scrollViewer.LineUp();
}
// 标记事件已处理
e.Handled = true;
}
else
{
// 如果找不到 ScrollViewer回退到事件传递
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = sender;
listBox.RaiseEvent(eventArg);
e.Handled = true;
}
}
}
}
/// <summary>
/// 添加获取 ScrollViewer 的辅助方法
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
private static ScrollViewer GetScrollViewer(DependencyObject element)
{
if (element is ScrollViewer scrollViewer)
return scrollViewer;
// 尝试从控件模板中查找 ScrollViewer
ScrollViewer result = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element) && result == null; i++)
{
var child = VisualTreeHelper.GetChild(element, i);
result = GetScrollViewer(child); // 递归查找
}
return result;
}
/// <summary>
/// 查找父级 ListBox
/// </summary>
/// <param name="child"></param>
/// <returns></returns>
private static ListBox FindParentListBox(DependencyObject child)
{
var parent = VisualTreeHelper.GetParent(child);
while (parent != null && !(parent is ListBox))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent as ListBox;
}
public static bool GetAutoSynchronizeChildren(DependencyObject obj)
{
return (bool)obj.GetValue(AutoSynchronizeChildrenProperty);
}
public static void SetAutoSynchronizeChildren(DependencyObject obj, bool value)
{
obj.SetValue(AutoSynchronizeChildrenProperty, value);
}
private static void OnAutoSynchronizeChildrenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ListBox listBox && (bool)e.NewValue)
{
// 监听 ListBox 的 Loaded 事件
listBox.Loaded += ListBox_Loaded;
// 监听 ItemContainerGenerator 状态变化,处理动态加载的项
listBox.ItemContainerGenerator.StatusChanged += (s, args) =>
{
if (listBox.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
AttachToAllDataGrids(listBox);
}
};
}
}
private static void ListBox_Loaded(object sender, RoutedEventArgs e)
{
if (sender is ListBox listBox)
{
AttachToAllDataGrids(listBox);
}
}
private static void AttachToAllDataGrids(ListBox listBox)
{
var dataGrids = FindVisualChildren<DataGrid>(listBox);
foreach (var dataGrid in dataGrids)
{
SetSynchronizeWithParent(dataGrid, true);
}
}
/// 查找所有指定类型的可视化子元素
private static IEnumerable<T> FindVisualChildren<T>(DependencyObject obj) where T : DependencyObject
{
if (obj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}
}