mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
743 lines
28 KiB
C#
743 lines
28 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Input;
|
||
using System.Windows.Media;
|
||
|
||
namespace AIStudio.Wpf.DiagramDesigner.Helpers
|
||
{
|
||
public static class VisualHelper
|
||
{
|
||
#region BindCommand
|
||
|
||
/// <summary>
|
||
/// 绑定命令和命令事件到宿主UI
|
||
/// </summary>
|
||
public static void BindCommand(this UIElement @ui, ICommand com, Action<object, ExecutedRoutedEventArgs> call)
|
||
{
|
||
var bind = new CommandBinding(com);
|
||
bind.Executed += new ExecutedRoutedEventHandler(call);
|
||
@ui.CommandBindings.Add(bind);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绑定RelayCommand命令到宿主UI
|
||
/// </summary>
|
||
public static void BindCommand(this UIElement @ui, ICommand com, object cancelExcute)
|
||
{
|
||
var bind = new CommandBinding(com);
|
||
@ui.CommandBindings.Add(bind);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region TreeView操作扩展方法
|
||
//code:http://www.codeproject.com/Articles/36193/WPF-TreeView-tools
|
||
|
||
/// <summary>
|
||
/// Returns the TreeViewItem of a data bound object.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <returns>The TreeViewItem of the data bound object or null.</returns>
|
||
public static TreeViewItem GetItemFromObject(this TreeView treeView, object obj)
|
||
{
|
||
try
|
||
{
|
||
DependencyObject dObject = GetContainerFormObject(treeView, obj);
|
||
TreeViewItem tvi = dObject as TreeViewItem;
|
||
while (tvi == null)
|
||
{
|
||
dObject = VisualTreeHelper.GetParent(dObject);
|
||
tvi = dObject as TreeViewItem;
|
||
}
|
||
return tvi;
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static DependencyObject GetContainerFormObject(ItemsControl item, object obj)
|
||
{
|
||
if (item == null)
|
||
return null;
|
||
|
||
DependencyObject dObject = null;
|
||
dObject = item.ItemContainerGenerator.ContainerFromItem(obj);
|
||
|
||
if (dObject != null)
|
||
return dObject;
|
||
|
||
var query = from childItem in item.Items.Cast<object>()
|
||
let childControl = item.ItemContainerGenerator.ContainerFromItem(childItem) as ItemsControl
|
||
select GetContainerFormObject(childControl, obj);
|
||
|
||
return query.FirstOrDefault(i => i != null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Selects a data bound object of a TreeView.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
public static void SelectObject(this TreeView treeView, object obj)
|
||
{
|
||
treeView.SelectObject(obj, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Selects or deselects a data bound object of a TreeView.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <param name="selected">select or deselect</param>
|
||
public static void SelectObject(this TreeView treeView, object obj, bool selected)
|
||
{
|
||
var tvi = treeView.GetItemFromObject(obj);
|
||
if (tvi != null)
|
||
{
|
||
tvi.IsSelected = selected;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns if a data bound object of a TreeView is selected.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <returns>Returns true if the object is selected, and false if it is not selected or obj is not in the tree.</returns>
|
||
public static bool IsObjectSelected(this TreeView treeView, object obj)
|
||
{
|
||
var tvi = treeView.GetItemFromObject(obj);
|
||
if (tvi != null)
|
||
{
|
||
return tvi.IsSelected;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns if a data bound object of a TreeView is focused.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <returns>Returns true if the object is focused, and false if it is not focused or obj is not in the tree.</returns>
|
||
public static bool IsObjectFocused(this TreeView treeView, object obj)
|
||
{
|
||
var tvi = treeView.GetItemFromObject(obj);
|
||
if (tvi != null)
|
||
{
|
||
return tvi.IsFocused;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Expands a data bound object of a TreeView.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
public static void ExpandObject(this TreeView treeView, object obj)
|
||
{
|
||
treeView.ExpandObject(obj, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Expands or collapses a data bound object of a TreeView.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <param name="expanded">expand or collapse</param>
|
||
public static void ExpandObject(this TreeView treeView, object obj, bool expanded)
|
||
{
|
||
var tvi = treeView.GetItemFromObject(obj);
|
||
if (tvi != null)
|
||
{
|
||
tvi.IsExpanded = expanded;
|
||
if (expanded)
|
||
{
|
||
// update layout, so that following calls to f.e. SelectObject on child nodes will
|
||
// find theire TreeViewNodes
|
||
treeView.UpdateLayout();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns if a douta bound object of a TreeView is expanded.
|
||
/// </summary>
|
||
/// <param name="treeView">TreeView</param>
|
||
/// <param name="obj">Data bound object</param>
|
||
/// <returns>Returns true if the object is expanded, and false if it is collapsed or obj is not in the tree.</returns>
|
||
public static bool IsObjectExpanded(this TreeView treeView, object obj)
|
||
{
|
||
var tvi = treeView.GetItemFromObject(obj);
|
||
if (tvi != null)
|
||
{
|
||
return tvi.IsExpanded;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Retuns the parent TreeViewItem.
|
||
/// </summary>
|
||
/// <param name="item">TreeViewItem</param>
|
||
/// <returns>Parent TreeViewItem</returns>
|
||
public static TreeViewItem GetParentItem(this TreeViewItem item)
|
||
{
|
||
var dObject = VisualTreeHelper.GetParent(item);
|
||
TreeViewItem tvi = dObject as TreeViewItem;
|
||
while (tvi == null)
|
||
{
|
||
dObject = VisualTreeHelper.GetParent(dObject);
|
||
tvi = dObject as TreeViewItem;
|
||
}
|
||
return tvi;
|
||
}
|
||
|
||
#endregion
|
||
|
||
public static T GetChild<T>(DependencyObject d) where T : DependencyObject
|
||
{
|
||
if (d is T t) return t;
|
||
|
||
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++)
|
||
{
|
||
var child = VisualTreeHelper.GetChild(d, i);
|
||
|
||
var result = GetChild<T>(child);
|
||
if (result != null) return result;
|
||
}
|
||
|
||
return default;
|
||
}
|
||
|
||
#region FindParent/FindChildren
|
||
/// <summary>
|
||
/// Finds a parent of a given item on the visual tree.
|
||
/// </summary>
|
||
/// <typeparam name="T">The type of the queried item.</typeparam>
|
||
/// <param name="child">A direct or indirect child of the
|
||
/// queried item.</param>
|
||
/// <returns>The first parent item that matches the submitted
|
||
/// type parameter. If not matching item can be found, a null
|
||
/// reference is being returned.</returns>
|
||
public static T TryFindParent<T>(this DependencyObject child)
|
||
where T : DependencyObject
|
||
{
|
||
//get parent item
|
||
DependencyObject parentObject = GetParentObject(child);
|
||
|
||
//we've reached the end of the tree
|
||
if (parentObject == null) return null;
|
||
|
||
//check if the parent matches the type we're looking for
|
||
T parent = parentObject as T;
|
||
return parent ?? TryFindParent<T>(parentObject);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Finds a Child of a given item in the visual tree.
|
||
/// </summary>
|
||
/// <param name="parent">A direct parent of the queried item.</param>
|
||
/// <typeparam name="T">The type of the queried item.</typeparam>
|
||
/// <param name="childName">x:Name or Name of child. </param>
|
||
/// <returns>The first parent item that matches the submitted type parameter.
|
||
/// If not matching item can be found,
|
||
/// a null parent is being returned.</returns>
|
||
public static T FindChild<T>(this DependencyObject parent, string childName = null)
|
||
where T : DependencyObject
|
||
{
|
||
// Confirm parent and childName are valid.
|
||
if (parent == null) return null;
|
||
|
||
T foundChild = null;
|
||
|
||
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||
for (int i = 0; i < childrenCount; i++)
|
||
{
|
||
var child = VisualTreeHelper.GetChild(parent, i);
|
||
// If the child is not of the request child type child
|
||
T childType = child as T;
|
||
if (childType == null)
|
||
{
|
||
// recursively drill down the tree
|
||
foundChild = FindChild<T>(child, childName);
|
||
|
||
// If the child is found, break so we do not overwrite the found child.
|
||
if (foundChild != null) break;
|
||
}
|
||
else if (!string.IsNullOrEmpty(childName))
|
||
{
|
||
var frameworkElement = child as FrameworkElement;
|
||
// If the child's name is set for search
|
||
if (frameworkElement != null && frameworkElement.Name == childName)
|
||
{
|
||
// if the child's name is of the request name
|
||
foundChild = (T)child;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// child element found.
|
||
foundChild = (T)child;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return foundChild;
|
||
}
|
||
|
||
/// <summary>
|
||
/// This will search for a child of the specified type. The search is performed
|
||
/// hierarchically, breadth first (as opposed to depth first).
|
||
/// </summary>
|
||
/// <typeparam name="T">The type of the element to find</typeparam>
|
||
/// <param name="parent">The root of the tree to search for. This element itself is not checked.</param>
|
||
/// <param name="additionalCheck">Provide a callback to check additional properties
|
||
/// of the found elements. Can be left Null if no additional criteria are needed.</param>
|
||
/// <returns>Returns the found element. Null if nothing is found.</returns>
|
||
/// <example>Button button = TreeHelper.FindChild<Button>( this, foundChild => foundChild.Focusable );</example>
|
||
public static T FindChild<T>(DependencyObject parent, Func<T, bool> additionalCheck) where T : DependencyObject
|
||
{
|
||
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||
T child;
|
||
|
||
for (int index = 0; index < childrenCount; index++)
|
||
{
|
||
child = VisualTreeHelper.GetChild(parent, index) as T;
|
||
|
||
if (child != null)
|
||
{
|
||
if (additionalCheck == null)
|
||
{
|
||
return child;
|
||
}
|
||
else
|
||
{
|
||
if (additionalCheck(child))
|
||
return child;
|
||
}
|
||
}
|
||
}
|
||
|
||
for (int index = 0; index < childrenCount; index++)
|
||
{
|
||
child = FindChild<T>(VisualTreeHelper.GetChild(parent, index), additionalCheck);
|
||
|
||
if (child != null)
|
||
return child;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// This method is an alternative to WPF's
|
||
/// <see cref="VisualTreeHelper.GetParent"/> method, which also
|
||
/// supports content elements. Keep in mind that for content element,
|
||
/// this method falls back to the logical tree of the element!
|
||
/// </summary>
|
||
/// <param name="child">The item to be processed.</param>
|
||
/// <returns>The submitted item's parent, if available. Otherwise
|
||
/// null.</returns>
|
||
public static DependencyObject GetParentObject(this DependencyObject child)
|
||
{
|
||
if (child == null) return null;
|
||
|
||
//handle content elements separately
|
||
var contentElement = child as ContentElement;
|
||
if (contentElement != null)
|
||
{
|
||
DependencyObject parent = ContentOperations.GetParent(contentElement);
|
||
if (parent != null) return parent;
|
||
|
||
var fce = contentElement as FrameworkContentElement;
|
||
return fce != null ? fce.Parent : null;
|
||
}
|
||
|
||
//also try searching for parent in framework elements (such as DockPanel, etc)
|
||
var frameworkElement = child as FrameworkElement;
|
||
if (frameworkElement != null)
|
||
{
|
||
DependencyObject parent = frameworkElement.Parent;
|
||
if (parent != null) return parent;
|
||
}
|
||
|
||
//if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
|
||
return VisualTreeHelper.GetParent(child);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Analyzes both visual and logical tree in order to find all elements of a given
|
||
/// type that are descendants of the <paramref name="source"/> item.
|
||
/// </summary>
|
||
/// <typeparam name="T">The type of the queried items.</typeparam>
|
||
/// <param name="source">The root element that marks the source of the search. If the
|
||
/// source is already of the requested type, it will not be included in the result.</param>
|
||
/// <param name="forceUsingTheVisualTreeHelper">Sometimes it's better to search in the VisualTree (e.g. in tests)</param>
|
||
/// <returns>All descendants of <paramref name="source"/> that match the requested type.</returns>
|
||
public static IEnumerable<T> FindChildren<T>(this DependencyObject source, bool forceUsingTheVisualTreeHelper = false) where T : DependencyObject
|
||
{
|
||
if (source != null)
|
||
{
|
||
var childs = GetChildObjects(source, forceUsingTheVisualTreeHelper);
|
||
foreach (DependencyObject child in childs)
|
||
{
|
||
//analyze if children match the requested type
|
||
if (child != null && child is T)
|
||
{
|
||
yield return (T)child;
|
||
}
|
||
|
||
//recurse tree
|
||
foreach (T descendant in FindChildren<T>(child))
|
||
{
|
||
yield return descendant;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// This method is an alternative to WPF's
|
||
/// <see cref="VisualTreeHelper.GetChild"/> method, which also
|
||
/// supports content elements. Keep in mind that for content elements,
|
||
/// this method falls back to the logical tree of the element.
|
||
/// </summary>
|
||
/// <param name="parent">The item to be processed.</param>
|
||
/// <param name="forceUsingTheVisualTreeHelper">Sometimes it's better to search in the VisualTree (e.g. in tests)</param>
|
||
/// <returns>The submitted item's child elements, if available.</returns>
|
||
public static IEnumerable<DependencyObject> GetChildObjects(this DependencyObject parent, bool forceUsingTheVisualTreeHelper = false)
|
||
{
|
||
if (parent == null) yield break;
|
||
|
||
if (!forceUsingTheVisualTreeHelper && (parent is ContentElement || parent is FrameworkElement))
|
||
{
|
||
//use the logical tree for content / framework elements
|
||
foreach (object obj in LogicalTreeHelper.GetChildren(parent))
|
||
{
|
||
var depObj = obj as DependencyObject;
|
||
if (depObj != null) yield return (DependencyObject)obj;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//use the visual tree per default
|
||
int count = VisualTreeHelper.GetChildrenCount(parent);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
yield return VisualTreeHelper.GetChild(parent, i);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Tries to locate a given item within the visual tree,
|
||
/// starting with the dependency object at a given position.
|
||
/// </summary>
|
||
/// <typeparam name="T">The type of the element to be found
|
||
/// on the visual tree of the element at the given location.</typeparam>
|
||
/// <param name="reference">The main element which is used to perform
|
||
/// hit testing.</param>
|
||
/// <param name="point">The position to be evaluated on the origin.</param>
|
||
public static T TryFindFromPoint<T>(UIElement reference, Point point)
|
||
where T : DependencyObject
|
||
{
|
||
var element = reference.InputHitTest(point) as DependencyObject;
|
||
|
||
if (element == null)
|
||
return null;
|
||
if (element is T)
|
||
return (T)element;
|
||
return TryFindParent<T>(element);
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 返回指定对象的特定类型的祖先。
|
||
/// </summary>
|
||
/// <typeparam name="T">要获取的祖先的类型。</typeparam>
|
||
/// <param name="source">获取的祖先,如果不存在则为 <c>null</c>。</param>
|
||
/// <returns>获取的祖先对象。</returns>
|
||
public static T GetAncestor<T>(DependencyObject source)
|
||
where T : DependencyObject
|
||
{
|
||
if (source == null)
|
||
return null;
|
||
do
|
||
{
|
||
source = VisualTreeHelper.GetParent(source);
|
||
} while (source != null && !(source is T));
|
||
|
||
return source as T;
|
||
}
|
||
|
||
private static DependencyObject GetParent(DependencyObject element)
|
||
{
|
||
Visual visual = element as Visual;
|
||
DependencyObject parent = (visual == null) ? null : VisualTreeHelper.GetParent(visual);
|
||
|
||
if (parent == null)
|
||
{
|
||
// No Visual parent. Check in the logical tree.
|
||
FrameworkElement fe = element as FrameworkElement;
|
||
|
||
if (fe != null)
|
||
{
|
||
parent = fe.Parent;
|
||
|
||
if (parent == null)
|
||
{
|
||
parent = fe.TemplatedParent;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
FrameworkContentElement fce = element as FrameworkContentElement;
|
||
|
||
if (fce != null)
|
||
{
|
||
parent = fce.Parent;
|
||
|
||
if (parent == null)
|
||
{
|
||
parent = fce.TemplatedParent;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return parent;
|
||
}
|
||
|
||
public static bool IsDescendantOf(DependencyObject element, DependencyObject parent)
|
||
{
|
||
while (element != null)
|
||
{
|
||
if (element == parent)
|
||
return true;
|
||
|
||
element = GetParent(element);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找元素的子元素
|
||
/// </summary>
|
||
/// <typeparam name="T">子元素类型</typeparam>
|
||
/// <param name="obj"></param>
|
||
/// <returns></returns>
|
||
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
|
||
{
|
||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||
{
|
||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||
if (child != null && child is T)
|
||
return (T)child;
|
||
else
|
||
{
|
||
T childOfChild = FindVisualChild<T>(child);
|
||
if (childOfChild != null)
|
||
return childOfChild;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 得到指定元素的集合
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="depObj"></param>
|
||
/// <returns></returns>
|
||
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
|
||
{
|
||
if (depObj != null)
|
||
{
|
||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
||
{
|
||
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
|
||
if (child != null && child is T)
|
||
{
|
||
yield return (T)child;
|
||
}
|
||
|
||
foreach (T childOfChild in FindVisualChildren<T>(child))
|
||
{
|
||
yield return childOfChild;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 利用visualtreehelper寻找对象的子级对象
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="obj"></param>
|
||
/// <returns></returns>
|
||
public static List<T> FindVisualChildrenEx<T>(DependencyObject obj) where T : DependencyObject
|
||
{
|
||
try
|
||
{
|
||
List<T> TList = new List<T> { };
|
||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||
{
|
||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||
if (child != null && child is T)
|
||
{
|
||
TList.Add((T)child);
|
||
List<T> childOfChildren = FindVisualChildrenEx<T>(child);
|
||
if (childOfChildren != null)
|
||
{
|
||
TList.AddRange(childOfChildren);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
List<T> childOfChildren = FindVisualChildrenEx<T>(child);
|
||
if (childOfChildren != null)
|
||
{
|
||
TList.AddRange(childOfChildren);
|
||
}
|
||
}
|
||
}
|
||
return TList;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找元素的父元素
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="i_dp"></param>
|
||
/// <returns></returns>
|
||
public static T FindParent<T>(DependencyObject i_dp) where T : DependencyObject
|
||
{
|
||
DependencyObject dobj = (DependencyObject)VisualTreeHelper.GetParent(i_dp);
|
||
if (dobj != null)
|
||
{
|
||
if (dobj is T)
|
||
{
|
||
return (T)dobj;
|
||
}
|
||
else
|
||
{
|
||
dobj = FindParent<T>(dobj);
|
||
if (dobj != null && dobj is T)
|
||
{
|
||
return (T)dobj;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public static T FindParent<T>(DependencyObject i_dp, string elementName) where T : DependencyObject
|
||
{
|
||
DependencyObject dobj = (DependencyObject)VisualTreeHelper.GetParent(i_dp);
|
||
if (dobj != null)
|
||
{
|
||
if (dobj is T && ((System.Windows.FrameworkElement)(dobj)).Name.Equals(elementName))
|
||
{
|
||
return (T)dobj;
|
||
}
|
||
else
|
||
{
|
||
dobj = FindParent<T>(dobj);
|
||
if (dobj != null && dobj is T)
|
||
{
|
||
return (T)dobj;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找指定名称的元素
|
||
/// </summary>
|
||
/// <typeparam name="childItem">元素类型</typeparam>
|
||
/// <param name="obj"></param>
|
||
/// <param name="elementName">元素名称,及xaml中的Name</param>
|
||
/// <returns></returns>
|
||
public static childItem FindVisualElement<childItem>(DependencyObject obj, string elementName) where childItem : DependencyObject
|
||
{
|
||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||
{
|
||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||
if (child != null && child is childItem && ((System.Windows.FrameworkElement)(child)).Name.Equals(elementName))
|
||
return (childItem)child;
|
||
else
|
||
{
|
||
IEnumerator j = FindVisualChildren<childItem>(child).GetEnumerator();
|
||
while (j.MoveNext())
|
||
{
|
||
childItem childOfChild = (childItem)j.Current;
|
||
|
||
if (childOfChild != null && !(childOfChild as FrameworkElement).Name.Equals(elementName))
|
||
{
|
||
FindVisualElement<childItem>(childOfChild, elementName);
|
||
}
|
||
else
|
||
{
|
||
return childOfChild;
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 命中测试。根据当前选中元素,查找视觉树父节点与子节点,看是否存在指定类型的元素
|
||
/// </summary>
|
||
/// <typeparam name="T">想命中的元素类型</typeparam>
|
||
/// <param name="dp">当前选中元素</param>
|
||
/// <returns>true:命中成功</returns>
|
||
public static bool HitTest<T>(DependencyObject dp) where T : DependencyObject
|
||
{
|
||
return FindParent<T>(dp) != null || FindVisualChild<T>(dp) != null;
|
||
}
|
||
|
||
public static T FindEqualElement<T>(DependencyObject source, DependencyObject element) where T : DependencyObject
|
||
{
|
||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(source); i++)
|
||
{
|
||
DependencyObject child = VisualTreeHelper.GetChild(source, i);
|
||
if (child != null && child is T && child == element)
|
||
{
|
||
return (T)child;
|
||
}
|
||
else
|
||
{
|
||
T childOfChild = FindVisualChild<T>(child);
|
||
if (childOfChild != null)
|
||
{
|
||
return childOfChild;
|
||
}
|
||
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
|
||
}
|
||
}
|