WPF 利用视觉树获取指定名称对象、指定类型对象、以及判断是否有验证错误

1.利用视觉树获取指定名称对象

cs 复制代码
/// <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 GetChildWithName<T>(this DependencyObject parent, string childName)
   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 = GetChildWithName<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;
}

2.返回指定类型的子对象

比如:在一个Grid内部有很多TextBox/ComboBox ,需要获取这个控件对象。

var children=Grid.GetChildren(new List<Type>(){ typeof(TextBox),typeof(ComboBox)});

cs 复制代码
/// <summary>
/// 返回指定类型的子对象
/// </summary>
/// <param name="p_element"></param>
/// <param name="includeTypes"></param>
/// <returns></returns>
public static IEnumerable<UIElement> GetChildren(this DependencyObject p_element, List<Type> includeTypes)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(p_element); i++)
    {
        var child = VisualTreeHelper.GetChild(p_element, i) as UIElement;
        if (child == null)
        {
            continue;
        }

        Type type = child.GetType();

        if (includeTypes.Contains(type))
        {
            yield return child;
        }
        else
        {
            foreach (var c in child.GetChildren(includeTypes))
            {
                yield return c;
            }
        }
    }
}

3.获取UI对象(UserControl)内部是否存在验证错误

string errorMsg=string.Empty;

if(UserControl.GetChildrenValidationHasError<TextBox>(ref errorMsg))

{

//UserControl 内部的TextBox 有验证错误

MessageBox.Show(errorMsg);//提示错误消息

}

cs 复制代码
/// <summary>
/// 获取当前DependencyObject(含特定类型子对象)是否存在Validation错误
/// </summary>
/// <param name="p_element"></param>
/// <param name="errorMsg"></param>
/// <returns></returns>
public static bool GetChildrenValidationHasError<T>(this DependencyObject p_element, ref string errorMsg) where T : UIElement
{
    var children = GetChildren<T>(p_element);
    foreach (var child in children)
    {
        if (CheckDependencyObjectHasError(child, ref errorMsg))
        {
            return true;
        }
    }
    return false;
}

/// <summary>
/// 获取当前DependencyObject(含所有UI子对象)是否存在Validation错误
/// </summary>
/// <param name="p_element"></param>
/// <param name="errorMsg"></param>
/// <returns></returns>
public static bool GetChildrenValidationHasError(this DependencyObject p_element, List<Type> includeTypes, ref string errorMsg)
{
    var children = GetChildren(p_element, includeTypes);
    foreach (var child in children)
    {
        if (CheckDependencyObjectHasError(child, ref errorMsg))
        {
            return true;
        }
    }
    return false;
}

/// <summary>
/// 获取当前DependencyObject是否存在Validation错误
/// </summary>
/// <param name="child"></param>
/// <param name="errorMsg"></param>
/// <returns></returns>
public static bool CheckDependencyObjectHasError(this DependencyObject child, ref string errorMsg)
{
    if (child != null && Validation.GetHasError(child))
    {
        var errors = Validation.GetErrors(child);
        if (errors != null)
        {
            errorMsg = string.Join("\n\r", errors.Select(m => m.ErrorContent).ToArray());
        }
        return true;
    }
    return false;
}
相关推荐
xcLeigh16 小时前
WPF进阶 | WPF 数据绑定进阶:绑定模式、转换器与验证
c#·wpf
学与用3 天前
【deepseek实战】绿色好用,不断网
ai·c#·wpf
的不对不4 天前
WPF基础03——InitializeComponent()函数解释
windows·c#·.net·wpf
军训猫猫头4 天前
61.异步编程1 C#例子 WPF例子
开发语言·c#·wpf
时光追逐者4 天前
一组开源、免费、Metro风格的 WPF UI 控件库
ui·开源·c#·.net·wpf·.netcore·微软技术
军训猫猫头5 天前
58.界面参数传递给Command C#例子 WPF例子
开发语言·ui·c#·wpf
xcLeigh6 天前
WPF基础 | 深入 WPF 事件机制:路由事件与自定义事件处理
c#·wpf
军训猫猫头7 天前
60.await与sleep的原理分析 C#例子 WPF例子
开发语言·ui·c#·wpf
敲代码的TKP8 天前
WPF自定义布局--瀑布布局
wpf
xcLeigh8 天前
WPF基础 | WPF 基础概念全解析:布局、控件与事件
c#·wpf