1

I apologize if the title is bad, I do not exactly know how to express myself about this issue.

I have a program written in C#, WPF, where I have a number of TabItems. inside these TabItems I have a couple of textboxes, checkboxes etc. Inside these "main" TabItems are also additional TabItems containing textboxes, checkboxes etc. What I want to do is to be able to store all values from these controls in a xml file. I have managed to do so for all the visible ones by standing in one of the main TabItems and executing the following code:

List<TextBox> allTxt = FindVisualChildren<TextBox>(this).ToList<TextBox>(); // this here is my MainWindow (Interaction logic for MainWindow.xaml)
   foreach (TextBox t in allTxt)
        list.Add(t.Name + ":" + t.Text); // list is a List I store these in
//The same goes later for checkboxes etc. 

I then store these in the desired file and this works fine, for the visible ones. But how can I do in order to include all the controls from all the "second" TabItems as well as all the ones from the "main" ones? I have tested to change the Selected TabItem to increse this one after the first one is complete but this does not seem to be working...

Basic sketch of the program (and No, I did not receive a good grade "art class")

erikduvet
  • 291
  • 2
  • 6
  • 16

3 Answers3

1

Perhaps something of a "brute force" method, but it's clean and easy to read...

List<String> textBoxes = new List<String>();
List<String> checkBoxes = new List<String>();
foreach (TabPage mainPage in mainTabControl.TabPages)
{
    foreach (Control c in mainPage.Controls)
    {
        if (c is TabControl)
        {
            foreach (TabPage secondPage in ((TabControl)c).TabPages)
            {
                foreach (Control c2 in secondPage.Controls)
                {
                    if (c is CheckBox)
                        checkBoxes.Add(((CheckBox)c).Name + ":" + (((CheckBox)c).Checked ? "True" : "False"));
                    else if (c is TextBox)
                        textBoxes.Add(((TextBox)c).Name + ":" + (((TextBox)c).Text));
                    //... add more for other controls to capture
                }
            }
        }
        else
        {
            if (c is CheckBox)
                checkBoxes.Add(((CheckBox)c).Name + ":" + (((CheckBox)c).Checked ? "True" : "False"));
            else if (c is TextBox)
                textBoxes.Add(((TextBox)c).Name + ":" + (((TextBox)c).Text));
            //... add more for other controls to capture
        }
    }
}
DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
  • You could always write a recursive function, it would make it look neater. – Bob. Jun 05 '13 at 12:15
  • @Bob. That's debatable. Depending upon the experience of your audience, recursive functions can be quite confusing. But personally, I have used them a lot, so I would agree. – DonBoitnott Jun 05 '13 at 12:19
  • True enough. Although, the more levels you add, the longer your function will get. Not really sure where the neat and messy boundary would be then. lol – Bob. Jun 05 '13 at 12:21
  • @Bob Absolutely correct! I would not extend this any further. In fact, you are correct to suggest that this method I have presented is based on the assumption that there are just the two layers. Any more, and you'd better consider alternatives. – DonBoitnott Jun 05 '13 at 12:23
  • This looks interesting, thanks for the responses. I have also been reading up on caching the Application Data and Data Binding so I'll see what works best before accepting any answers. But thanks again! – erikduvet Jun 07 '13 at 09:07
0

You should give names to inner tabs and then search tham using their names. Here you can find some explanation: find control by name

Community
  • 1
  • 1
  • This did not directly solve my issue though I get null on my TextBox = ... after the call to that function with the correct name on the child... I however see a point in the solution but takes gladly more advice! – erikduvet Jun 05 '13 at 11:26
  • you should use that function for getting list of tabs, and than for each tab check their textboxes with function you are already using in question you posted – Mustafa Duranovic Jun 05 '13 at 12:43
0

As an alternative to iterating all the controls you could also consider data-binding them. That way you'd just have to get the data from the data source and write it to the XML file.

There'd have to be a property for each control in the class and in your XAML you'd have to bind each control to its property. Then you'd have to set the window's data context to an instance of the class.

You might want to read a bit about WPF data binding.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139