유형별로 WPF 창에서 모든 컨트롤 찾기 있습니다. 예를 들어 : 모두 찾기 TextBoxes,

Window에서 모든 컨트롤을 유형별로 찾는 방법을 찾고 있습니다.

예를 들어 : 모두 찾기 TextBoxes, 특정 인터페이스를 구현하는 모든 컨트롤 찾기 등



답변

이 트릭을해야합니다

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;
            }
        }
    }
}

그런 다음 컨트롤을 열거합니다.

foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
    // do something with tb here
}


답변

가장 쉬운 방법입니다.

IEnumerable<myType> collection = control.Children.OfType<myType>(); 

여기서 control은 창의 루트 요소입니다.


답변

@Bryce Kahle의 답변을 @Mathias Lykkegaard Lorenzen의 제안과 사용에 따라 조정했습니다 LogicalTreeHelper.

잘 작동하는 것 같습니다. 😉

public static IEnumerable<T> FindLogicalChildren<T> ( DependencyObject depObj ) where T : DependencyObject
{
    if( depObj != null )
    {
        foreach( object rawChild in LogicalTreeHelper.GetChildren( depObj ) )
        {
            if( rawChild is DependencyObject )
            {
                DependencyObject child = (DependencyObject)rawChild;
                if( child is T )
                {
                    yield return (T)child;
                }

                foreach( T childOfChild in FindLogicalChildren<T>( child ) )
                {
                    yield return childOfChild;
                }
            }
        }
    }
}

(여전히 @Benjamin Berry & @David R에서 언급 한대로 GroupBox 내부의 탭 컨트롤 또는 그리드를 확인하지 않습니다.) (또한 @noonand의 제안을 따르고 중복 자식을 제거했습니다! = null)


답변

헬퍼 클래스를 사용 VisualTreeHelper하거나 관심 LogicalTreeHelper있는 트리 에 따라 다를 수 있습니다. 둘 다 요소의 하위를 가져 오는 메소드를 제공합니다 (구문이 약간 다르지만). 필자는 종종 이러한 클래스를 사용하여 특정 유형의 첫 번째 항목을 찾았지만 해당 유형의 모든 객체를 찾도록 쉽게 수정할 수 있습니다.

public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
    if (obj != null)
    {
        if (obj.GetType() == type)
        {
            return obj;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type);
            if (childReturn != null)
            {
                return childReturn;
            }
        }
    }

    return null;
}


답변

VisualTreeHelper.GetChildrenCount(depObj);위의 여러 예제에서 사용 된 행 은 GroupBoxes에 대해 0이 아닌 카운트를 반환하지 않는 것으로 나타났습니다 . 특히 GroupBoxcontains 포함 GridGridcontains 하위 요소가 있습니다. 나는 이것이 GroupBox둘 이상의 자녀를 포함 할 수 없기 때문에 이것이 가능하다고 생각 하며, 이것은 그 Content재산에 저장됩니다 . GroupBox.Children속성 유형 이 없습니다 . 이 작업을 매우 효율적으로 수행하지는 않았지만이 체인에서 첫 번째 “FindVisualChildren”예제를 다음과 같이 수정했습니다.

public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        int depObjCount = VisualTreeHelper.GetChildrenCount(depObj);
        for (int i = 0; i <depObjCount; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                yield return (T)child;
            }

            if (child is GroupBox)
            {
                GroupBox gb = child as GroupBox;
                Object gpchild = gb.Content;
                if (gpchild is T)
                {
                    yield return (T)child;
                    child = gpchild as T;
                }
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
} 


답변

특정 유형의 모든 자식 목록을 얻으려면 다음을 사용할 수 있습니다.

private static IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, Type type)
{
    if (obj != null)
    {
        if (obj.GetType() == type)
        {
            yield return obj;
        }

        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
            {
                if (child != null)
                {
                    yield return child;
                }
            }
        }
    }

    yield break;
}


답변

예를 들어 탭 컨트롤의 자식 탭 컨트롤을 찾을 수 있도록 재귀를 약간 변경합니다.

    public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
    {
        if (obj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);

                if (child.GetType() == type)
                {
                    return child;
                }

                DependencyObject childReturn = FindInVisualTreeDown(child, type);
                if (childReturn != null)
                {
                    return childReturn;
                }
            }
        }

        return null;
    }