0

I am trying to loop through child elements of a Tab Control to know what Check Boxes are set to checked or not checked. I have found various answers on SO, but I can't seem to get the code to do what I need. Here is what I have thus far:

foreach (System.Windows.Controls.TabItem page in this.MainWindowTabControl.Items)
{
      if(VisualTreeHelper.GetChild(page, 0).GetType() == typeof(System.Windows.Controls.Grid))
      {
          var grid = VisualTreeHelper.GetChild(page, 0);
          int gridChildCount = VisualTreeHelper.GetChildrenCount(grid);
          for(int i = 0; i < gridChildCount; i++)
          {
              if(VisualTreeHelper.GetChild(grid, i).GetType() == typeof(CheckBox))
              {
                  CheckBox box = (CheckBox)VisualTreeHelper.GetChild(grid, i);
                  if (boxer.IsChecked == true)
                        checkboxes.Add(box);
              }
          }
          //do work
      }
}

Most likely, I am thinking incorrectly about how the VisualTreeHelper class works. I imagine I can keep working though the XAML Code to keep moving into deeper and deeper children of the Tab Control? Currently, my code on my WPF's xaml looks like this:

<TabControl x:Name="MainWindowTabControl" HorizontalAlignment="Left" Height="470" 
    Margin="0,10,0,0" VerticalAlignment="Top" Width="1384">
        <TabItem Header="TabItem">
            <Grid Background="#FFE5E5E5" Margin="0,-21,0,0">
                <CheckBox Name="testBox" Content="Check Box" 
            HorizontalAlignment="Left" VerticalAlignment="Top" Margin="1293,50,0,0"/>
           </Grid>
        </TabItem>
</TabControl>

So, my understanding is that I have to work from child to child, meaning, use the VisualTreeHelper to get the Children of the Tab Control (select Tab Item), then get the children of the TabItem (select the grid), then get the children of Grid, and then I can finally loop through the children (checkboxes) to get the information I want. If I am mistaken can someone please explain where I am going wrong?

EDIT: Changed Checkbox XAML to the proper code

Rinktacular
  • 1,116
  • 3
  • 19
  • 45
  • 2
    Databind those checkboxes to a viewmodel array of boolean values. Then iterate through that collection. That's the WPF (aka MVVM) way to do it. – code4life Oct 11 '16 at 17:18
  • @code4life Still relatively new to C#, what is the reason or purpose behind that methodology? – Rinktacular Oct 11 '16 at 17:24
  • Do yourself a serious favor and learn the MVVM pattern. It's a different way of thinking about programming than you are used to, but it will make WPF development far easier. If you don't use it, you will end up fighting with WPF almost every step of the way. – Bradley Uffner Oct 11 '16 at 17:24
  • Also, try not to use the `Margin` property to absolutely position elements. You should be using `Grid` and other layout controls to do this. – Bradley Uffner Oct 11 '16 at 17:27
  • @BradleyUffner Well I would like to become better in any way, so I suppose it is time to learn. Will learning the MVVM pattern help solve my issue? Or is it just so different that its hard to compare the two? – Rinktacular Oct 11 '16 at 17:27
  • I think it will make your problem easier to solve, as you won't have to deal with the visual tree at all. All the UI is bound to properties on a ViewModel, which is just a regular class. So your problem just becomes looking at those Boolean properties instead of messing with the Visual Tree. – Bradley Uffner Oct 11 '16 at 17:29
  • 1
    @Rinktacular: MVVM is the fundamental technology behind WPF. It means that you don't have to work with extracting data from visual controls anymore - using bindings, you simply pour the data back and forth between the domain objects and the visual elements without any plumbing code required on your part. – code4life Oct 11 '16 at 17:29
  • @code4life, thank you for your help. Looks like I have some research to do on the topic. Would never have known I was doing anything wrong without your help :) – Rinktacular Oct 11 '16 at 17:33
  • @BradleyUffner and thank you to you as well! – Rinktacular Oct 11 '16 at 17:33
  • 1
    What you are doing isn't really "wrong". There are some rare cases in WPF where you may actually have to crawl the Visual Tree in strange ways, but it isn't very common. As @code4life stated, WPF was designed for the MVVM pattern, things will just go far better for you if you try to stick to it as much as you can. – Bradley Uffner Oct 11 '16 at 17:41

1 Answers1

1

As far as my knowledge goes, there is no need to do what you're doing to get the children from a parent. You can use the LogicalTreeHelper class. It will let you query objects through the GetChildren method.
Your code should look like this:
XAML:

<TabControl x:Name="MainWindowTabControl" HorizontalAlignment="Left" 
Margin="0,10,0,0" VerticalAlignment="Top" Height="181" Width="247">
        <TabItem Header="TabItem">
            <Grid Background="#FFE5E5E5" Margin="0,-21,0,0" x:Name="gridChk">
                <CheckBox x:Name="testBox" Content="Check Box" 
        HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,50,0,0"/>
            </Grid>
        </TabItem>
    </TabControl>

C#:

    List<CheckBox> boxesList = new List<CheckBox>();
    //The named Grid, and not TabControl
    var children = LogicalTreeHelper.GetChildren(gridChk); 

    //Loop through each child
    foreach (var item in children)
    {
        var chkCast = item as CheckBox;
        //Check if the CheckBox object is checked
        if (chkCast.IsChecked == true)
        {
            boxesList.Add(chkCast);
        }
    }
FF-
  • 732
  • 9
  • 19
  • That works perfectly! I'll plan to learn to WVVM as others commented, but this does work for the purpose of this question. Thank you very much! – Rinktacular Oct 11 '16 at 21:40