Nested Controls

Like the Controls collection in a Win or WebForms, WPF controls have an ownership hierarchy. A Window may own a GroupBox, and that GroupBox may own a CheckBox, and so on. Suppose you were to lay out this interface using the visual designer. The XAML looks like Listing 6-11.

Listing 6-11. XAML for Nested Containers

<Window x:Class="DataDrivenWPF.GridDemo"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Grid" Height="300" Width="300"> <Grid>

<Button Height="23" Margin="101,0,102,12" Name="cmdGetData" VerticalAlignment="Bottom"

Click="cmdGetData_Click">Get Data</Button> <GroupBox Header="My Data" Margin="38,46,34,73" Name="groupBox1"> <Grid>

<CheckBox Margin="44,54,30,54" Name="checkBox1">Check Me</CheckBox> </Grid> </GroupBox> </Grid> </Window>

And the window looks like Figure 6-12.

Figure 6-12. Nested containers

Note the hierarchy in the XAML. The Window contains a Grid that contains a GroupBox that contains another Grid that contains a CheckBox. To iterate through this hierarchy, you need to resort to recursion. You must bear in mind a few considerations about recursing through a WPF control tree. As noted in the previous section, the owner Window doesn't have a Controls collection. Rather, it has a Content property. This property is of type object, and it must be cast to a specific container control object in order to access its Children property. You can accomplish this using the method shown in Listing 6-12.

Listing 6-12. Referencing Child Control Collections private UIElementCollection GetUIElementCollection(object oContent) {

UIElementCollection oUIElementCollection = null;

switch (oContent.GetType().Name) {

case "Grid":

oUIElementCollection = ((Grid) oContent).Children; break;

case "StackPanel":

oUIElementCollection = ((StackPanel) oContent).Children; break;

case "DockPanel":

oUIElementCollection = ((DockPanel) oContent).Children; break;

case "Canvas":

oUIElementCollection = ((Canvas) oContent).Children; break;

return oUIElementCollection;

After the type of the child container has been determined, you can iterate through its component elements. If one of these elements is an owner to many controls—say, like a GroupBox—then you can cast its Content property to the appropriate container object and continue the recursion. When you draw a GroupBox on a Window, for example, it automatically displays with a Grid container inside it. Because a GroupBox is intended to hold multiple controls, you therefore need a container like a Grid to handle the content. Thus, to iterate through a series of nested controls on a Window, you can use the recursive IterateControls() method shown in Listing 6-13.

Listing 6-13. Iter a teCon trol s () Method private void IterateControls(UIElementCollection oUIElementCollection) {

Grid oGrid = null; GroupBox oGroupBox = null; StackPanel oStackPanel = null;

foreach (UIElement oElement in oUIElementCollection) {

switch (oElement.GetType().Name) {

case "TextBox":

szData += ((TextBox) oElement).Text + "\n"; break;

case "ComboBox":

szData += ((ComboBox)oElement).Text + "\n"; break;

case "CheckBox":

szData += ((CheckBox)oElement).Content.ToString() + "\n"; break;

case "Button":

szData += ((Button)oElement).Content.ToString() + "\n";

break;

case "GroupBox":

oGroupBox = ((GroupBox) oElement); szData += oGroupBox.Header + "\n";

IterateControls(GetUIElementCollection(oGroupBox.Content)); break;

case "Grid":

IterateControls(oGrid.Children);

break;

case "StackPanel":

oStackPanel = ((StackPanel) oElement); IterateControls(oStackPanel.Children); break;

This method iterates through the elements in a UIElementCollection object. After the object type is determined, you can use the appropriate property to extract its value. If the object type is a container, the property that references it UIElementCollection object is passed to IterateControls(), and the recursion continues.

0 0

Post a comment