2

I am very new to WPF and just would to ask your help for a very basic method of getting the Windows controls and their children as in Winform app. Bottom line is to have reusable code for multiple window/pages in a different different class.

Bunches of thanks before.

Public Sub GetControl(Wn As Window)
    For Each Ctrl As Control In Wn.Controls
        'Code here

        If Ctrl.HasChildren = True Then
            'Code here
        End If
    Next
End Sub
  • Possible duplicate of [WPF: How do I loop through the all controls in a window?](http://stackoverflow.com/questions/874380/wpf-how-do-i-loop-through-the-all-controls-in-a-window) – mm8 Mar 30 '17 at 15:01
  • http://stackoverflow.com/questions/974598/find-all-controls-in-wpf-window-by-type – Greg Mulvihill May 01 '17 at 22:26

1 Answers1

2

So here's the down low. You need to look for UIElement, which is a base class for all UIElements in XAML. There are two main types that host controls. ContentControl and Panel.
A ContentControl has a 'Content' property that is potentially containing an object. A Panel has a collection of UIElements property 'Children' and of type UIElement.

If you're looking just for the elements of a Window or ANY UIElement then you need to recursively search and make that list based on that information.

A Window inherits from ContentControl but that Content might be a Grid or StackPanel or any Panel or sorts and may have Children of UIElement also.

You cycle through them all until you get the results.

public MainWindow()
{
        InitializeComponent();

        foreach (var element in GetAllElementsFrom(this))
            Debug.WriteLine(element.ToString());
}

private IEnumerable<UIElement> GetAllElementsFrom(UIElement element)
{
    var uiElements = GetSingleElement();

       switch (element)
       {
            case Panel panel:
                foreach (var child in panel.Children)
                    uiElements = uiElements.Concat(GetInnerElements(child));
                break;
            case UserControl userControl:
                uiElements = uiElements.Concat(GetInnerElements(userControl.Content));
                break;
            case ContentControl contentControl:
                if (contentControl.Content is UIElement uiElement)
                    uiElements = uiElements.Concat(GetInnerElements(uiElement));
                break;
        }

    return uiElements;

    IEnumerable<UIElement> GetSingleElement()
    {
        yield return element;
    }
}

Here's the XAML I used.

<Grid>
    <Button>
        <DockPanel>
            <ContentControl>
                <Grid>
                    <TextBox />
                </Grid>
            </ContentControl>
        </DockPanel>
    </Button>

    <StackPanel>
        <Label />
        <TextBlock>
            Hey There!!
        </TextBlock>
        <Grid>
            <Ellipse />
        </Grid>
    </StackPanel>
</Grid>

And here's the result I got in my debug window:

System.Windows.Controls.Grid
System.Windows.Controls.Button
System.Windows.Controls.DockPanel
System.Windows.Controls.ContentControl
System.Windows.Controls.Grid
System.Windows.Controls.TextBox
System.Windows.Controls.StackPanel
System.Windows.Controls.Label
System.Windows.Controls.TextBlock
System.Windows.Controls.Grid
System.Windows.Shapes.Ellipse

Happy Coding! Note: Uses C# 7 syntax; if you're not on C# 7 then just make the changes, I think they're straight forward.

Michael Puckett II
  • 6,586
  • 5
  • 26
  • 46
  • While C# 7 syntax is cleaver, the OP stated "I am very new to WPF", so it is probably not the best way to answer the question. Thank you for your answer regardless. – Greg Mulvihill May 01 '17 at 22:29
  • @GregMulvihill I apologize but I thought I gave details about the answer in depth so that you could understand it. Regardless of C# 7 syntax and C# 7 has nothing to do with WPF. – Michael Puckett II May 02 '17 at 04:58
  • 1
    @GregMulvihill However; I do see that you wrote your example is VB.NET and not C# so I apologize. But, the same concept is used for both. Just read the description of traversing the elements. You can do the same in VB.NET and if you want I'll update the answer in VB. – Michael Puckett II May 02 '17 at 04:59
  • You should leave what you have contributed, it serves as a good example of C# 7... if you feel compelled, add a VB.NET version. – Greg Mulvihill May 02 '17 at 18:29