Hey everyone,
As you all know, all I used to do was code all my stuff in Windows Forms. I’ve decided to switch over to WPF so I’m gently and at my own pace migrating from Windows Forms to WPF.
Everyone knows that when you migrate from one thing to another, you’ll always bump into the following problem:
“I was able to do this before, how am I supposed to do this now? ”
That has already happend a few times to me while working in WPF.
One of this issues I recently had, was that in Windows Forms it was easy to iterate over all the controls located within a form or container (GroupBox for example).
In WPF, it obviously didn’t work that way >.<
As an example, the following code in Windows Forms:
foreach(Control c in GroupBox1.Controls) { if(c.GetType() == typeof(TextBox)) { TextBox txt = (TextBox)c; txt.Clear(); } }
This would clear all textboxes located within GroupBox1.
Now, when you try to do that in WPF, you’ll notice that the GroupBox doesn’t have a Controls property.
So I had to put together a little helper that would get all the child controls for me and how deep they’d be nested:
class ChildControls { private List<object> lstChildren; public List<object> GetChildren(Visual p_vParent, int p_nLevel) { if (p_vParent == null) { throw new ArgumentNullException("Element {0} is null!", p_vParent.ToString()); } this.lstChildren = new List<object>(); this.GetChildControls(p_vParent, p_nLevel); return this.lstChildren; } private void GetChildControls(Visual p_vParent, int p_nLevel) { int nChildCount = VisualTreeHelper.GetChildrenCount(p_vParent); for (int i = 0; i <= nChildCount - 1; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(p_vParent, i); lstChildren.Add((object)v); if (VisualTreeHelper.GetChildrenCount(v) > 0) { GetChildControls(v, p_nLevel + 1); } } } }
Now with that class, I can simply do the following:
ChildControls ccChildren = new ChildControls(); foreach (object o in ccChildren.GetChildren(GroupBox1, 5)) { if (o.GetType() == typeof(TextBox)) { TextBox txt = (TextBox)o; txt.Text = ""; } }
Note that the 5 in “.GetChildren(GroupBox1, 5)” indicates how many levels deep I’d like to check for controls.
When you have a layout that contains deeply nested XAML code, you can easily increase this number, especially when requesting child controls for top level elements
Hehe.. Might want to look into the databinding functionality of WPF 😉 Winforms sux! ;P
Duuurrrrrrrrrrr, I hate you 😛
Go start your own blog instead of trolling mine! 😀
I know there are probably easier ways or better ways then what I’ve just proposed. I just haven’t discovered it yet.
You can also do this:
foreach (var c in LogicalTreeHelper.GetChildren(GroupBox1)) {
if (c is TextBox) {
(c as TextBox).clear();
}
}
Hey Nate,
Won’t that snippet only loop over the children of the control and not the children of the children etc?
As in:
GroupBox1 –> GroupBox2 -> GroupBox3 –> TextBox2 won’t be found by that snippet?
and only
GroupBox1 –> TextBox1 will be found?
Thanks for the comment btw, it’s always nice to know someone is reading ;P
– Dirk
thanks, this saved me some time 🙂
Hi Dirk,
After hours of trying to weed through the assistance that I found on the other blogs, I landed on your page. You’re a life saver…works great. This implementation is flexible enough to tool and retool for most anything a person wants to do with the controls on a form.
Good job and thanks!
I do have one question though. If I have several groupboxes on a form — what control do I replace the groupBox1 parameter with? The form name?
Okay, I answered my own question — to itereate through the entire form use the “this” keyword.
This saves my hours of working… thnx brother 🙂
This is one of the best articles I read online. No crap, just useful information. Very well presented. This link…
http://mindstick.com/Blog/155/How%20to%20find%20Child%20of%20control%20in%20WPF
also helped me to complete my task.
Thanks Everyone!!
U can add all controls in this and will work great, thxs
ChildControls ccChildren = new ChildControls();
foreach (object o in ccChildren.GetChildren(GroupBox1, 5))
{
if (o.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)o;
txt.Text = “”;
}
if (o.GetType() == typeof(ComboBox))
{
ComboBox cm = (ComboBox)o;
cm.SelectedIndex = -1;
}
if (o.GetType() == typeof(CheckBox))
{
CheckBox chk = (CheckBox)o;
chk.IsChecked = false;
}
if (o.GetType() == typeof(RadioButton))
{
RadioButton chk = (RadioButton)o;
chk.IsChecked = false;
}
if (o.GetType() == typeof(DatePicker))
{
DatePicker dtp = (DatePicker)o;
dtp.SelectedDate = null;
}
}
// Reset de Controles en WPF
// WPF Reset Controls
The List WinForms control offers many advanced data features like grouping, sorting and filtering and large flexibility to be customized.
Dirk, you are hero. Thanks guy.
First off, thanks for the code! It worked for the most part in my case. My issue is the method is not clearing the controls for the remaining TabItems which are not selected. Other than that, it works great! Any suggestions on how to edit this so it’ll clear the rest of the controls in my TabItem’s Grid? Thanks!
hello, I have a question: You have used the data type in your ChildControls class as Visual, while I am unable to use it in my code. I tried to look into it on the internet, but I found nothing. Can you please explain what the Visual data type is?
Hello Meeha,
When I wrote this article, I had just started to learn WPF (coming from a Winforms background).
Several years later, I’ve had some WPF experiences and I can no longer recommend this approach.
Pretty much anything can be done in WPF as long as you apply the MVVM pattern or use behaviors.
That being said, the “Visual” class resides inside the “System.Windows.Media” namespace which is located in the “System.Windows” assembly.
Add a reference to “System.Windows” in your project and you should have access to the “Visual” class.
The class is abstract and inherits from DependencyObject.
Thanks Nate!
foreach (var c in LogicalTreeHelper.GetChildren(maingrid))
It helped me.
This is old and outdated, in addition, you have left us hanging with your last post on it. Please provide a way to return a list of all controls (recursively) on a WPF form (please assume the whole form not just a control 5 layers down). I would greatly appreciate it. Thank you in advance.
Oh yeah and the old code did not specify any references or using statements, could you please include those?
Hey LarryH,
This is an old post indeed and I can no longer condone this kind of approach…
I do no longer have the source code for this code snippet, although Visual Studio should be able to resolve the using statements that you need.
As far as I can tell, the snippet keeps going down the visual tree until it no longer encounters any controls… It doesn’t do anything with the specified level :/
Thanks Dirk,
I’ve trying to figure this out for three days as I am new to programming.
Although the solution came from Nate (Thanks Nate), I would never have found such a simple way to loop through the child controls.
Thanks Again
And on solving life who we apply your method .
thanks
Great article!
You solved my issue in 0 time.
Thank you very much Dirk 😀
Dude,
I know this is a 10+ year old post, but it delivers. Clear, concise, easy to use, no BS. Thanks a lot. I’d buy you a drink if I could 😉