2025-02-10 20:53:40 +08:00
|
|
|
|
using System;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
namespace WPFluent.Extensions
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
public static class VisualExtensions
|
|
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static T FindEqualElement<T>(DependencyObject source, DependencyObject element)
|
|
|
|
|
|
where T : DependencyObject
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(source); i++)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
var child = VisualTreeHelper.GetChild(source, i);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (child != null && child is T t && child == element)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
return t;
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var childOfChild = FindVisualChild<T>(child);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (childOfChild != null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
2024-09-22 11:05:41 +08:00
|
|
|
|
return childOfChild;
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
/// 查找元素的父元素
|
2024-09-22 11:05:41 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
/// <param name="i_dp"></param>
|
2024-09-22 11:05:41 +08:00
|
|
|
|
/// <returns></returns>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static T FindParent<T>(this DependencyObject i_dp) where T : DependencyObject
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
var dobj = VisualTreeHelper.GetParent(i_dp);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj is T t)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return t;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
dobj = FindParent<T>(dobj);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj is not null and T)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return (T)dobj;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
2025-02-10 20:53:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static T FindParent<T>(this DependencyObject i_dp, string elementName) where T : DependencyObject
|
|
|
|
|
|
{
|
|
|
|
|
|
var dobj = VisualTreeHelper.GetParent(i_dp);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj != null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj is T && ((System.Windows.FrameworkElement)(dobj)).Name.Equals(elementName))
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
return (T)dobj;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
dobj = FindParent<T>(dobj);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (dobj is not null and T)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return (T)dobj;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return null;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
/// 查找元素的子元素
|
2024-09-22 11:05:41 +08:00
|
|
|
|
/// </summary>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
/// <typeparam name="T">子元素类型</typeparam>
|
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static T FindVisualChild<T>(this DependencyObject obj) where T : DependencyObject
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
var child = VisualTreeHelper.GetChild(obj, i);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (child is not null and T)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return (T)child;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var childOfChild = FindVisualChild<T>(child);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (childOfChild != null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return childOfChild;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 得到指定元素的集合
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
|
/// <param name="depObj"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
|
|
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (depObj != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
var child = VisualTreeHelper.GetChild(depObj, i);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (child is not null and T)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
yield return (T)child;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
2025-02-10 20:53:40 +08:00
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
foreach (var childOfChild in FindVisualChildren<T>(child))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
yield return childOfChild;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 利用visualtreehelper寻找对象的子级对象
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static List<T> FindVisualChildrenEx<T>(this DependencyObject obj) where T : DependencyObject
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
List<T> TList = [];
|
2025-05-05 17:04:06 +08:00
|
|
|
|
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var child = VisualTreeHelper.GetChild(obj, i);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (child is not null and T)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
TList.Add((T)child);
|
|
|
|
|
|
var childOfChildren = FindVisualChildrenEx<T>(child);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (childOfChildren != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
TList.AddRange(childOfChildren);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var childOfChildren = FindVisualChildrenEx<T>(child);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (childOfChildren != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
TList.AddRange(childOfChildren);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return TList;
|
2025-05-05 17:04:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 查找指定名称的元素
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="childItem">元素类型</typeparam>
|
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
|
/// <param name="elementName">元素名称,及xaml中的Name</param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static childItem FindVisualElement<childItem>(this DependencyObject obj, string elementName)
|
|
|
|
|
|
where childItem : DependencyObject
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var child = VisualTreeHelper.GetChild(obj, i);
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (child != null &&
|
2025-02-10 20:53:40 +08:00
|
|
|
|
child is childItem &&
|
|
|
|
|
|
((System.Windows.FrameworkElement)(child)).Name.Equals(elementName))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
return (childItem)child;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
IEnumerator j = FindVisualChildren<childItem>(child).GetEnumerator();
|
2025-05-05 17:04:06 +08:00
|
|
|
|
while (j.MoveNext())
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var childOfChild = (childItem)j.Current;
|
|
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (childOfChild != null && !(childOfChild as FrameworkElement).Name.Equals(elementName))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
FindVisualElement<childItem>(childOfChild, elementName);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return childOfChild;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the dependency property according to its name.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="type">The type.</param>
|
|
|
|
|
|
/// <param name="propertyName">Name of the property.</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static DependencyProperty GetDependencyProperty(Type type, string propertyName)
|
|
|
|
|
|
{
|
|
|
|
|
|
DependencyProperty prop = null;
|
|
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (type != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-02-10 20:53:40 +08:00
|
|
|
|
var fieldInfo = type.GetField($"{propertyName}Property", BindingFlags.Static | BindingFlags.Public);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (fieldInfo != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
prop = fieldInfo.GetValue(null) as DependencyProperty;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return prop;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Retrieves a <see cref="DependencyProperty"/> using reflection.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="o"></param>
|
|
|
|
|
|
/// <param name="propertyName"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static DependencyProperty GetDependencyProperty(this DependencyObject o, string propertyName)
|
|
|
|
|
|
{
|
|
|
|
|
|
DependencyProperty prop = null;
|
|
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (o != null)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
prop = GetDependencyProperty(o.GetType(), propertyName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return prop;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-10 20:53:40 +08:00
|
|
|
|
public static IntPtr GetHandle(this Visual visual)
|
|
|
|
|
|
{ return (PresentationSource.FromVisual(visual) as HwndSource)?.Handle ?? IntPtr.Zero; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取属性
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static object GetPropertyValue(this object obj, string path)
|
|
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (obj == null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
return string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
var flag = !string.IsNullOrEmpty(path);
|
|
|
|
|
|
object result;
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (flag)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
var property = obj.GetType().GetProperty(path);
|
|
|
|
|
|
var flag2 = property != null;
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (flag2)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
result = property.GetValue(obj, null);
|
|
|
|
|
|
return result;
|
2025-05-05 17:04:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var type = obj.GetType();
|
|
|
|
|
|
var mInfo = type.GetMethod($"get_{path}");
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (mInfo != null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
result = mInfo.Invoke(obj, null);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2025-05-05 17:04:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch
|
2025-02-10 20:53:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
result = obj;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 命中测试。根据当前选中元素,查找视觉树父节点与子节点,看是否存在指定类型的元素
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T">想命中的元素类型</typeparam>
|
|
|
|
|
|
/// <param name="dp">当前选中元素</param>
|
|
|
|
|
|
/// <returns>true:命中成功</returns>
|
|
|
|
|
|
public static bool HitTest<T>(this DependencyObject dp) where T : DependencyObject
|
|
|
|
|
|
{ return FindParent<T>(dp) != null || FindVisualChild<T>(dp) != null; }
|
|
|
|
|
|
|
2024-09-22 11:05:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置 <paramref name="property"/> 只有在没有明确设置的情况下才会使用。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
|
/// <param name="o">The object.</param>
|
|
|
|
|
|
/// <param name="property">The property.</param>
|
|
|
|
|
|
/// <param name="value">The value.</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static bool SetIfDefault<T>(this DependencyObject o, DependencyProperty property, T value)
|
|
|
|
|
|
{
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (o == null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
throw new ArgumentNullException(nameof(o), "DependencyObject cannot be null");
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (property == null)
|
2025-02-10 20:53:40 +08:00
|
|
|
|
throw new ArgumentNullException(nameof(property), "DependencyProperty cannot be null");
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (!property.PropertyType.IsAssignableFrom(typeof(T)))
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentException(
|
2025-02-10 20:53:40 +08:00
|
|
|
|
$"Expected {property.Name} to be of type {typeof(T).Name} but was {property.PropertyType}");
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-05 17:04:06 +08:00
|
|
|
|
if (DependencyPropertyHelper.GetValueSource(o, property).BaseValueSource == BaseValueSource.Default)
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
o.SetValue(property, value);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|