function that returns a IEnumerable<T> with yield return - winforms

I have a function that only returns the first parent item.
public static T FindControlParent<T>(this Control control) where T : Control
{
T parent = default;
if (control.Parent != null)
{
if (control.Parent.GetType() == typeof(T))
{
return (T)control.Parent;
}
return FindControlParent<T>(control.Parent);
}
return parent;
}
I have a button, which is inside two panels, I would like a function that returns a list of the two panels of the button.
something like
Form>panel1>panel2>GroupBox>button
var panelsFinded = FindControlParents<Panel>(button1);
//values: panel1, panel2

I managed to solve it, someone correct me if it can get better
public static IEnumerable<T> FindControlParent2<T>(Control control)
where T : Control
{
if (control != null)
{
Control parent = control.Parent;
if (parent is T)
yield return(T)control.Parent;
foreach (var i in FindControlParent2<T>(parent.Parent))
yield return i;
}
}

Related

Select all combo boxes on winform by LINQ [duplicate]

I have multiple pictureboxes and I need to load random images into them during runtime. So I thought it would be nice to have a collection of all pictureboxes and then assign images to them using a simple loop. But how should I do it? Or maybe are there any other better solutions to such problem?
Using a bit of LINQ:
foreach(var pb in this.Controls.OfType<PictureBox>())
{
//do stuff
}
However, this will only take care of PictureBoxes in the main container.
You could use this method:
public static IEnumerable<T> GetControlsOfType<T>(Control root)
where T : Control
{
var t = root as T;
if (t != null)
yield return t;
var container = root as ContainerControl;
if (container != null)
foreach (Control c in container.Controls)
foreach (var i in GetControlsOfType<T>(c))
yield return i;
}
Then you could do something like this:
foreach (var pictureBox in GetControlsOfType<PictureBox>(theForm)) {
// ...
}
If you're at least on .NET 3.5 then you have LINQ, which means that since ControlCollection implements IEnumerable you can just do:
var pictureBoxes = Controls.OfType<PictureBox>();
I use this generic recursive method:
The assumption of this method is that if the control is T than the method does not look in its children. If you need also to look to its children you can easily change it accordingly.
public static IList<T> GetAllControlsRecusrvive<T>(Control control) where T :Control
{
var rtn = new List<T>();
foreach (Control item in control.Controls)
{
var ctr = item as T;
if (ctr!=null)
{
rtn.Add(ctr);
}
else
{
rtn.AddRange(GetAllControlsRecusrvive<T>(item));
}
}
return rtn;
}
A simple function, easy to understand, recursive, and it works calling it inside any form control:
private void findControlsOfType(Type type, Control.ControlCollection formControls, ref List<Control> controls)
{
foreach (Control control in formControls)
{
if (control.GetType() == type)
controls.Add(control);
if (control.Controls.Count > 0)
findControlsOfType(type, control.Controls, ref controls);
}
}
You can call it on multiple ways.
To get the Buttons:
List<Control> buttons = new List<Control>();
findControlsOfType(typeof(Button), this.Controls, ref buttons);
To get the Panels:
List<Control> panels = new List<Control>();
findControlsOfType(typeof(Panel), this.Controls, ref panels);
etc.
Here's another version since the existing provided ones weren't quite what I had in mind. This one works as an extension method, optionally, and it excludes checking the root/parent container's type. This method is basically a "Get all descendent controls of type T" method:
public static System.Collections.Generic.IEnumerable<T> ControlsOfType<T>(this System.Web.UI.Control control) where T: System.Web.UI.Control{
foreach(System.Web.UI.Control childControl in control.Controls){
if(childControl is T) yield return (T)childControl;
foreach(var furtherDescendantControl in childControl.ControlsOfType<T>()) yield return furtherDescendantControl;
}
}
public static List<T> FindControlByType<T>(Control mainControl,bool getAllChild = false) where T :Control
{
List<T> lt = new List<T>();
for (int i = 0; i < mainControl.Controls.Count; i++)
{
if (mainControl.Controls[i] is T) lt.Add((T)mainControl.Controls[i]);
if (getAllChild) lt.AddRange(FindControlByType<T>(mainControl.Controls[i], getAllChild));
}
return lt;
}
This to me is by far the easiest. In my application, I was trying to clear all the textboxes in a panel:
foreach (Control c in panel.Controls)
{
if (c.GetType().Name == "TextBox")
{
c.Text = "";
}
}
Takes Control as container into account:
private static IEnumerable<T> GetControlsOfType<T>(this Control root)
where T : Control
{
if (root is T t)
yield return t;
if (root is ContainerControl || root is Control)
{
var container = root as Control;
foreach (Control c in container.Controls)
foreach (var i in GetControlsOfType<T>(c))
yield return i;
}
}

WPF Nested User Control

I have build a WPF User Control which contains a ComboBox with a custom popup window which contains a User Control the inner control (the one in the popup) has some properties that I want to expose in the main user control so the host page can read and write to the inner control.
I am having trouble doing this is there something I am doing wrong or is what I am doing ill advised ?
Regards Christian Andersen
you can try exposing it using this
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) yield break;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var children = child as T;
if (children != null)
{
yield return children;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
How I use it
var uc = (TabItem)sender;
foreach (TextBlock textBlock in uc.FindVisualChildren<TextBlock>())
{
textBlock.Foreground = Brushes.WhiteSmoke;
}

Winforms bind SelectedItems in listbox

Using the standard listbox I would like to bind it to a set of objects and update a bound items collection to include those selected.
So I have something like:
_pContext = new BindingSource();
_pContext.DataSource = _gpContext;
_pContext.DataMember = "ParentEntities";
_AllChildrenListBox.DataSource = _container.ChildEntities;
_AllChildrenListBox.DataBindings.Add("MySelectedItems", _pContext, "ChildEntities", false);
_allChildrenListBox is the listbox. I created a new listbox type inheriting from ListBox so I could create an alternative SelectedItems property which would then encapsulate the logic to set/unset the items.
So the question in a nutshell is: In the above, ChildEntities is a collection of "ChildEntity" objects. My list box contains all possible ChildEntity objects and I want the elements in ChildEntities to be selected, and updated when selection changed.
I have found a way around this. It's a little ugly at the moment, but works. I can refine it later.
So first bit was the binding itself.
_AllChildrenListBox.DataBindings.Add("SelectedItems2", _pContext, "ChildEntities2", true);
The key here seemed to be setting the formatting parameter to true.
Next I needed something in SelectedItems2 that would do my dirty work. This is a mess, but works. Here's the full class:
public class MyListBox : ListBox
{
private IEnumerable<object> _original;
public IEnumerable<object> SelectedItems2
{
get
{
return UpdateSet();
}
set
{
SelectItems(value);
}
}
private IEnumerable<object> UpdateSet()
{
var listSource = _original as IListSource;
IList list = null;
if (listSource != null)
{
list = listSource.GetList();
}
var iList = _original as IList;
if (list == null && iList != null)
{
list = iList;
}
if (list == null)
{
return _original;
}
foreach (var item in SelectedItems)
{
if (!list.Contains(item))
{
list.Add(item);
}
}
foreach (var item in _original.ToList())
{
if (!SelectedItems.Contains(item))
{
list.Remove(item);
}
}
return _original;
}
private void SelectItems(IEnumerable<object> items)
{
_original = items;
var hashset = new HashSet<object>();
foreach (var item in items)
{
hashset.Add(item);
}
for(var i=0;i<Items.Count;i++)
{
SetSelected(i, hashset.Contains(Items[i]));
}
}
}
Essentially I'm breaking all the rules and assuming IEnumerable hides a more tasty list based interface, if it does it uses that to changes the underlying set.
Finally, I'm using EF (Entity Framework) and you can't call the setter of a collection property, so my entity currently looks like this: Notice how I'm duplicating all the list change operations which is totally unnecessary, but I did say this was just the first working go.
public partial class ParentEntity
{
public IEnumerable<object> ChildEntities2
{
get
{
return new List<object>(ChildEntities);
}
set
{
if (value == null)
{
return;
}
foreach (var item in ChildEntities.ToList().Where(item => !value.Contains(item)))
{
ChildEntities.Remove(item);
}
foreach (var item in value)
{
var cItem = item as ChildEntity;
if (cItem != null)
{
if (!ChildEntities.Contains(item as ChildEntity))
{
ChildEntities.Add(item as ChildEntity);
}
}
}
}
}
}

wpf how to get all TextBoxes in wpf application [duplicate]

I'm looking for a way to find all controls on Window by their type,
for example: find all TextBoxes, find all controls implementing specific interface etc.
This should do the trick:
public static IEnumerable<T> FindVisualChilds<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) yield return (T)Enumerable.Empty<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject ithChild = VisualTreeHelper.GetChild(depObj, i);
if (ithChild == null) continue;
if (ithChild is T t) yield return t;
foreach (T childOfChild in FindVisualChilds<T>(ithChild)) yield return childOfChild;
}
}
then you enumerate over the controls like so
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
}
This is the easiest way:
IEnumerable<myType> collection = control.Children.OfType<myType>();
where control is the root element of the window.
EDIT - As pointed out in the comments. This only goes one level deep. See the accepted answer for an option that goes deeper.
I adapted #Bryce Kahle's answer to follow #Mathias Lykkegaard Lorenzen's suggestion and use LogicalTreeHelper.
Seems to work okay. ;)
public static IEnumerable<T> FindLogicalChildren<T> ( DependencyObject depObj ) where T : DependencyObject
{
if( depObj != null )
{
foreach( object rawChild in LogicalTreeHelper.GetChildren( depObj ) )
{
if( rawChild is DependencyObject )
{
DependencyObject child = (DependencyObject)rawChild;
if( child is T )
{
yield return (T)child;
}
foreach( T childOfChild in FindLogicalChildren<T>( child ) )
{
yield return childOfChild;
}
}
}
}
}
(It still won't check tab controls or Grids inside GroupBoxes as mentioned by #Benjamin Berry & #David R respectively.)
(Also followed #noonand's suggestion & removed the redundant child != null)
Use the helper classes VisualTreeHelper or LogicalTreeHelper depending on which tree you're interested in. They both provide methods for getting the children of an element (although the syntax differs a little). I often use these classes for finding the first occurrence of a specific type, but you could easily modify it to find all objects of that type:
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
return obj;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
I found that the line, VisualTreeHelper.GetChildrenCount(depObj);, used in several examples above does not return a non-zero count for GroupBoxes, in particular, where the GroupBox contains a Grid, and the Grid contains children elements. I believe this may be because the GroupBox is not allowed to contain more than one child, and this is stored in its Content property. There is no GroupBox.Children type of property. I am sure I did not do this very efficiently, but I modified the first "FindVisualChildren" example in this chain as follows:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
int depObjCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i <depObjCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
if (child is GroupBox)
{
GroupBox gb = child as GroupBox;
Object gpchild = gb.Content;
if (gpchild is T)
{
yield return (T)child;
child = gpchild as T;
}
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Here is yet another, compact version, with the generics syntax:
public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject obj) where T : DependencyObject
{
if (obj != null) {
if (obj is T)
yield return obj as T;
foreach (DependencyObject child in LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>())
foreach (T c in FindLogicalChildren<T>(child))
yield return c;
}
}
To get a list of all childs of a specific type you can use:
private static IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
yield return obj;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
{
if (child != null)
{
yield return child;
}
}
}
}
yield break;
}
Small change to the recursion to so you can for example find the child tab control of a tab control.
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child.GetType() == type)
{
return child;
}
DependencyObject childReturn = FindInVisualTreeDown(child, type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
And this is how it works upwards
private T FindParent<T>(DependencyObject item, Type StopAt) where T : class
{
if (item is T)
{
return item as T;
}
else
{
DependencyObject _parent = VisualTreeHelper.GetParent(item);
if (_parent == null)
{
return default(T);
}
else
{
Type _type = _parent.GetType();
if (StopAt != null)
{
if ((_type.IsSubclassOf(StopAt) == true) || (_type == StopAt))
{
return null;
}
}
if ((_type.IsSubclassOf(typeof(T)) == true) || (_type == typeof(T)))
{
return _parent as T;
}
else
{
return FindParent<T>(_parent, StopAt);
}
}
}
}
Do note that using the VisualTreeHelper does only work on controls that derive from Visual or Visual3D. If you also need to inspect other elements (e.g. TextBlock, FlowDocument etc.), using VisualTreeHelper will throw an exception.
Here's an alternative that falls back to the logical tree if necessary:
http://www.hardcodet.net/2009/06/finding-elements-in-wpf-tree-both-ways
My version for C++/CLI
template < class T, class U >
bool Isinst(U u)
{
return dynamic_cast< T >(u) != nullptr;
}
template <typename T>
T FindVisualChildByType(Windows::UI::Xaml::DependencyObject^ element, Platform::String^ name)
{
if (Isinst<T>(element) && dynamic_cast<Windows::UI::Xaml::FrameworkElement^>(element)->Name == name)
{
return dynamic_cast<T>(element);
}
int childcount = Windows::UI::Xaml::Media::VisualTreeHelper::GetChildrenCount(element);
for (int i = 0; i < childcount; ++i)
{
auto childElement = FindVisualChildByType<T>(Windows::UI::Xaml::Media::VisualTreeHelper::GetChild(element, i), name);
if (childElement != nullptr)
{
return childElement;
}
}
return nullptr;
};
#Bryce, really nice answer.
VB.NET version:
Public Shared Iterator Function FindVisualChildren(Of T As DependencyObject)(depObj As DependencyObject) As IEnumerable(Of T)
If depObj IsNot Nothing Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child As DependencyObject = VisualTreeHelper.GetChild(depObj, i)
If child IsNot Nothing AndAlso TypeOf child Is T Then
Yield DirectCast(child, T)
End If
For Each childOfChild As T In FindVisualChildren(Of T)(child)
Yield childOfChild
Next
Next
End If
End Function
Usage (this disables all TextBoxes in a window):
For Each tb As TextBox In FindVisualChildren(Of TextBox)(Me)
tb.IsEnabled = False
Next
For this and more use cases you can add flowing extension method to your library:
public static List<DependencyObject> FindAllChildren(this DependencyObject dpo, Predicate<DependencyObject> predicate)
{
var results = new List<DependencyObject>();
if (predicate == null)
return results;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dpo); i++)
{
var child = VisualTreeHelper.GetChild(dpo, i);
if (predicate(child))
results.Add(child);
var subChildren = child.FindAllChildren(predicate);
results.AddRange(subChildren);
}
return results;
}
Example for your case:
var children = dpObject.FindAllChildren(child => child is TextBox);
I wanted to add a comment but I have less than 50 pts so I can only "Answer".
Be aware that if you use the "VisualTreeHelper" method to retrieve XAML "TextBlock" objects then it will also grab XAML "Button" objects. If you re-initialize the "TextBlock" object by writing to the Textblock.Text parameter then you will no longer be able to change the Button text using the Button.Content parameter. The Button will permanently show the text written to it from the Textblock.Text write action (from when it was retrieved --
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
tb.Text = ""; //this will overwrite Button.Content and render the
//Button.Content{set} permanently disabled.
}
To work around this, you can try using a XAML "TextBox" and add methods (or Events) to mimic a XAMAL Button. XAML "TextBox" is not gathered by a search for "TextBlock".
For some reason, none of the answers posted here helped me to get all controls of given type contained in a given control in my MainWindow.
I needed to find all menu items in one menu to iterate them. They were not all direct descendants of the menu, so i managed to collect only the first lilne of them using any of the code above.
This extension method is my solution for the problem for anyone who will continue to read all the way down here.
public static void FindVisualChildren<T>(this ICollection<T> children, DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
var brethren = LogicalTreeHelper.GetChildren(depObj);
var brethrenOfType = LogicalTreeHelper.GetChildren(depObj).OfType<T>();
foreach (var childOfType in brethrenOfType)
{
children.Add(childOfType);
}
foreach (var rawChild in brethren)
{
if (rawChild is DependencyObject)
{
var child = rawChild as DependencyObject;
FindVisualChildren<T>(children, child);
}
}
}
}
Hope it helps.
I found it easier without Visual Tree Helpers:
foreach (UIElement element in MainWindow.Children) {
if (element is TextBox) {
if ((element as TextBox).Text != "")
{
//Do something
}
}
};
The accepted answer returns the discovered elements more or less unordered, by following the first child branch as deep as possible, while yielding the discovered elements along the way, before backtracking and repeating the steps for not yet parsed tree branches.
If you need the descendent elements in descending order, where the direct children will be yielded first, then their children and so on, the following algorithm will work:
public static IEnumerable<T> GetVisualDescendants<T>(DependencyObject parent, bool applyTemplates = false)
where T : DependencyObject
{
if (parent == null || !(child is Visual || child is Visual3D))
yield break;
var descendants = new Queue<DependencyObject>();
descendants.Enqueue(parent);
while (descendants.Count > 0)
{
var currentDescendant = descendants.Dequeue();
if (applyTemplates)
(currentDescendant as FrameworkElement)?.ApplyTemplate();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(currentDescendant); i++)
{
var child = VisualTreeHelper.GetChild(currentDescendant, i);
if (child is Visual || child is Visual3D)
descendants.Enqueue(child);
if (child is T foundObject)
yield return foundObject;
}
}
}
The resulting elements will be ordered from nearest to farthest.
This will be useful e.g. if you are looking for the nearest child element of some type and condition:
var foundElement = GetDescendants<StackPanel>(someElement)
.FirstOrDefault(o => o.SomeProperty == SomeState);

Generic method to find all TextBox controls in Silverlight

I have several Silverlight controls on a page and want query all the controls that are of type TextBox and have that working.
Now the Silverlight form I'm working on could have more TextBox controls added. So when I test to see if a TextBox control has a value, I could do:
if (this.TextBox.Control.value.Text() != String.Empty)
{
// do whatever
}
but I'd rather have if flexible that I can use this on ANY Silverlight form regardless of the number of TextBox controls I have.
Any ideas on how I would go about doing that?
I have already faced this issue and notify it here : http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight
Here you have a generic method to find recursively in the VisualTree all TextBoxes:
IEnumerable<DependencyObject> GetChildrenRecursively(DependencyObject root)
{
List<DependencyObject> children = new List<DependencyObject>();
children.Add(root);
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
children.AddRange(GetChildrenRecursively(VisualTreeHelper.GetChild(root, i)));
return children;
}
Use this method like this to find all TextBoxes:
var textBoxes = GetChildrenRecursively(LayoutRoot).OfType<TextBox>();
It sounds like you need a recursive routine like GetTextBoxes below:
void Page_Loaded(object sender, RoutedEventArgs e)
{
// Instantiate a list of TextBoxes
List<TextBox> textBoxList = new List<TextBox>();
// Call GetTextBoxes function, passing in the root element,
// and the empty list of textboxes (LayoutRoot in this example)
GetTextBoxes(this.LayoutRoot, textBoxList);
// Now textBoxList contains a list of all the text boxes on your page.
// Find all the non empty textboxes, and put them into a list.
var nonEmptyTextBoxList = textBoxList.Where(txt => txt.Text != string.Empty).ToList();
// Do something with each non empty textbox.
nonEmptyTextBoxList.ForEach(txt => Debug.WriteLine(txt.Text));
}
private void GetTextBoxes(UIElement uiElement, List<TextBox> textBoxList)
{
TextBox textBox = uiElement as TextBox;
if (textBox != null)
{
// If the UIElement is a Textbox, add it to the list.
textBoxList.Add(textBox);
}
else
{
Panel panel = uiElement as Panel;
if (panel != null)
{
// If the UIElement is a panel, then loop through it's children
foreach (UIElement child in panel.Children)
{
GetTextBoxes(child, textBoxList);
}
}
}
}
Instantiate an empty list of TextBoxes. Call GetTextBoxes, passing in the root control on your page (in my case, that's this.LayoutRoot), and GetTextBoxes should recursively loop through every UI element that is a descendant of that control, testing to see if it's either a TextBox (add it to the list), or a panel, that might have descendants of it's own to recurse through.
Hope that helps. :)
From your top most panel you can do this (my grid is called ContentGrid)
var textBoxes = this.ContentGrid.Children.OfType<TextBox>();
var nonEmptyTextboxes = textBoxes.Where(t => !String.IsNullOrEmpty(t.Text));
foreach (var textBox in nonEmptyTextboxes)
{
//Do Something
}
However this will only find the textboxes that are immediate children. Some sort of recursion like below would help, but I'm thinking there must be a better way.
private List<TextBox> SearchForTextBoxes(Panel panel)
{
List<TextBox> list = new List<TextBox>();
list.AddRange(panel.Children.OfType<TextBox>()
.Where(t => !String.IsNullOrEmpty(t.Text)));
var panels = panel.Children.OfType<Panel>();
foreach (var childPanel in panels)
{
list.AddRange(SearchForTextBoxes(childPanel));
}
return list;
}
Took Scott's initial idea and expanded it so that it
Uses generics, so it easily copes with multiple control types.
Supports more container types. In my WP7 I needed to support panaorama's, scroll viewers etc... which aren't Panels. So this allows support for them.
Biggest issue is that string comparing, especially on the Panel and derrived items.
Code:
private static void GetControls<T>(UIElement uiElement, List<T> controlList) where T : UIElement
{
var frameworkFullName = uiElement.GetType().FullName;
if (frameworkFullName == typeof(T).FullName)
{
controlList.Add(uiElement as T);
return;
}
if (frameworkFullName == typeof(Panel).FullName ||
frameworkFullName == typeof(Grid).FullName ||
frameworkFullName == typeof(StackPanel).FullName)
{
foreach (var child in (uiElement as Panel).Children)
{
GetControls(child, controlList);
}
return;
}
if (frameworkFullName == typeof(Panorama).FullName)
{
foreach (PanoramaItem child in (uiElement as Panorama).Items)
{
var contentElement = child.Content as FrameworkElement;
if (contentElement != null)
{
GetControls(contentElement, controlList);
}
}
return;
}
if (frameworkFullName == typeof(ScrollViewer).FullName)
{
var contentElement = (uiElement as ScrollViewer).Content as FrameworkElement;
if (contentElement != null)
{
GetControls(contentElement, controlList);
}
return;
}
}
Similar logic to ideas above to also handle controls with a "Content" attribute like TabItems and Scrollviewers where children might be embedded at a lower level. Finds all children:
IEnumerable<DependencyObject> GetControlsRecursive(DependencyObject root)
{
List<DependencyObject> elts = new List<DependencyObject>();
elts.Add(root);
string type = root.GetType().ToString().Replace("System.Windows.Controls.", "");
switch (root.GetType().ToString().Replace("System.Windows.Controls.", ""))
{
case "TabItem":
var TabItem = (TabItem)root;
elts.AddRange(GetControlsRecursive((DependencyObject)TabItem.Content));
break;
case "ScrollViewer":
var Scroll = (ScrollViewer)root;
elts.AddRange(GetControlsRecursive((DependencyObject) Scroll.Content));
break;
default: //controls that have visual children go here
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) elts.AddRange(GetControlsRecursive(VisualTreeHelper.GetChild(root, i)));
break;
}
return elts;
}

Resources