Control looping

Hi, I have a panel and I want to loop through all the controls on it, to set certain properties like Text, etc. Is there an easy way of doing this

Answer this question

Control looping

  • vky

    I have never seen any problem with Children... It works extremelly fine up to now...

    Even in your second Grid, the one nested under the TabItem, there is only 1 Children... the ListBox...

    ListBox, in its turn, uses a Panel to layout its Items collection.... Where your other controls are placed...

    Although I believe that your suggestion of using the VisualTreeHelper is good for the sake of m_v's problem.




  • soccerdude1000

    No no, in my tests, I was just asking to display the components that were contains in a Control ;)

  • Dude987

    Thanks fo bringing that Thomas, could you please specify the scenarios in which Children property won't work (as that's one of the core assumptions we made in our code) Are you not talking about nesting things here

    Thanks


  • Etherline

    Yes, but I get the same problem when I was asking to display the children of the Grid in the TabItem (and in that Grid, there are buttons, ListBox, etc....)



  • swathi237

    Which makes perfect sense, considering that TabControl is the only Child of the Grid...
  • shark312

    Generally it depends on a type of the Panel (ItemsControl has Items collection, Canvas/Grids have Children property.

    For the general case you can use smth. like:

    foreach (FrameworkElement f in MyPanel.Children)

    {

    if (f is Label)  { … do processing for the label…}

    }

    I would suggest though to create strongly typed caches for every type of a child control, using generic collections. When you initially populate your control/screen with the child elements get them cached into generic collections like

    List<Label> labels = new List<Label>();

    labels.Add(new Label());

    that will save you a hassle when you will parse the contents back, instead of checking type of every individual control you can simply loop throw the collection (cache) of the well known type.

    Cheers


  • BushGates

    Marc Laroche wrote:
    I have never seen any problem with Children... It works extremelly fine up to now...

    Even in your second Grid, the one nested under the TabItem, there is only 1 Children... the ListBox...

    ListBox, in its turn, uses a Panel to layout its Items collection.... Where your other controls are placed...


    I know that, that's why I didn't understand myself... So I create the class which use VisualTreeHelper.


    Although I believe that your suggestion of using the VisualTreeHelper is good for the sake of m_v's problem.

    Thanks ;)



  • Brad King

    Sorry for the mess Thomas, but are you not actually reassigning those controls to a different parent when you're 'asking to display the children of the Grid in the TabItem' Or I really missed somthething...

     


  • sujun

    Thanks guys for replying.

    I have a method that loops through all the "controls" on a panel. When it gets another panel (or object with base-class panel) I call this method recursively again. If I hit a Label, I do something, if I hit a RadioButton, I do something else, and so on. I thought there might be a more "wpf" way of doing this, similar to styling.

    My problem, thought, is that when I get to an ItemsControl, that has items with their own templates that can contain anything, like stackpanels, labels, etc., the Items property in code has Count=0.

    Maybe it's because I start looping before the ItemsControl is "bound" to the templates. I start looping in the OnInitialized override of a Panel control.

    I will see what I come up with with the VisualTreeHelper class that you posted Thomas.

    Cheers


  • ondrej_bohaciak

    Children property will not work all the time...

    You can use this class to get a list of all the children's components of a control:

    class Utility
    {
    private static StringBuilder sbListControls;

    public static StringBuilder GetVisualTreeInfo(Visual element)
    {
    if (element == null)
    {
    throw new ArgumentNullException(String.Format("Element {0} is null !", element.ToString()));
    }

    sbListControls = new StringBuilder();

    GetControlsList(element, 0);

    return sbListControls;
    }

    private static void GetControlsList(Visual control, int level)
    {
    const int indent = 4;
    int ChildNumber = VisualTreeHelper.GetChildrenCount(control);

    for (int i = 0; i <= ChildNumber - 1; i++)
    {
    Visual v = (Visual)VisualTreeHelper.GetChild(control, i);

    sbListControls.Append(new string(' ', level * indent));
    sbListControls.Append(v.GetType());
    sbListControls.Append(Environment.NewLine);

    if (VisualTreeHelper.GetChildrenCount(v) > 0)
    {
    GetControlsList(v, level + 1);
    }
    }
    }
    }

    HTH.

    Bye



  • Darin Tomack

    Hi guys

    I used the VisualTreeHelper to loop through all the controls on a control, but I had the same problem with ItemsControls and ScrollViewers (I suspect other controls as well). It seems they "bind" their items later than when you just add controls in the XAML code.

    I moved my function call from the OnInitialized override to the OnRender override, and now it works. All the controls are bound, and I can walk through them with the VisualTreeHelper and set the required properties.

    Thanks for the suggestions and the nudges in the right direction.


  • Richard M Malone

    Here is sample code:

    <Grid>
    <TabControl Name="m_tbcDemonstration">
    <TabItem Name="m_tabDemoControls" Header="Les Controles">
    <Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="0.3*" />
    <ColumnDefinition Width="0.7*" />
    </Grid.ColumnDefinitions>

    <ListBox Name="m_lbListControls" Grid.Column="0" SelectionChanged="GetControlList" VerticalAlignment="Center" HorizontalAlignment="Center">
    <Button Content="Un bouton simple" />

    <Button>
    <CheckBox Content="Une bouton avec une CheckBox" />
    </Button>

    <Button>
    <Image Source="{Binding Source=Images/Winter.jpg}" MaxHeight="65" />
    </Button>

    <TextBox Text="Une Simple TextBox" />

    <ListBox>
    <ListBoxItem Content="Une ListBox dans une ListBox" />
    <ListBoxItem Content="2eme Item" />
    <ListBoxItem Content="3eme Item" />
    </ListBox>
    </ListBox>

    <TreeView Name="m_tvListControl" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" />
    </Grid>
    </TabItem>

    </TabControl>

    </Grid>

    If I use the Children property on the Grid control, it will display only 1 control.

    Indeed, Children is not a control's collection but a single control.



  • Control looping