I have a wpf application and I want to set everything to Focusable="false".
Is there an easy and elegant way? Currently I made a style for each type of Control I use like this:
<Style TargetType="Button">
<Setter Property="Focusable" Value="False"></Setter>
</Style>
Any idea for a more universan solution?
Why not try a two line solution ?
foreach (var ctrl in myWindow.GetChildren())
{
//Add codes here :)
}
Also make sure to add this :
public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true)
{
if (parent != null)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
// Retrieve child visual at specified index value.
var child = VisualTreeHelper.GetChild(parent, i) as Visual;
if (child != null)
{
yield return child;
if (recurse)
{
foreach (var grandChild in child.GetChildren(true))
{
yield return grandChild;
}
}
}
}
}
}
Or even shorter, use this :
public static IList<Control> GetControls(this DependencyObject parent)
{
var result = new List<Control>();
for (int x = 0; x < VisualTreeHelper.GetChildrenCount(parent); x++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, x);
var instance = child as Control;
if (null != instance)
result.Add(instance);
result.AddRange(child.GetControls());
}
return result;
}
I have some few cases in my WPF application that requires me to find a specific type of user control in a given user control. For example I'm having the following method that already works nicely:
public static System.Windows.Controls.CheckBox FindChildCheckBox(DependencyObject d)
{
try
{
System.Windows.Controls.CheckBox chkBox = d as System.Windows.Controls.CheckBox;
if (d != null && chkBox == null)
{
int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < count; i++)
{
chkBox = FindChildCheckBox(System.Windows.Media.VisualTreeHelper.GetChild(d, i));
if (chkBox != null)
break;
}
}
return chkBox;
}
catch
{
return null;
}
}
This method will help me to find a CheckBox in a given ListViewItem which allows me to check/uncheck the said CheckBox more conveniently.
However, I'd like to have this method more generic like for example:
public static T FindChildUserControl<T>(DependencyObject d)
Unfortunately I do not see how I can get this work. Can someone please help?
You need to replace CheckBox with T and add a generic restraint (where) to the type argument.
For example I'm having the following method that already works nicely
Which is odd, as far as I can tell it would only work on nested CheckBoxes. This should on any combination of controls:
public static T FindChild<T>(DependencyObject d) where T : DependencyObject
{
if (d is T)
return (T)d;
int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < count; i++)
{
DependencyObject child = FindChild<T>(System.Windows.Media.VisualTreeHelper.GetChild(d, i));
if (child != null)
return (T)child;
}
return null;
}
Usage:
CheckBox check = FindChild<CheckBox>(parent);
To get all children of a certain type, this should work nicely:
public static IEnumerable<T> FindChildren<T>(DependencyObject d) where T : DependencyObject
{
if (d is T)
yield return (T)d;
int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < count; i++)
{
foreach (T child in FindChildren<T>(System.Windows.Media.VisualTreeHelper.GetChild(d, i)))
yield return child;
}
}
Usage:
foreach(CheckBox c in FindChildren<CheckBox>(parent))
This method will help me to find a CheckBox in a given ListViewItem which allows me to check/uncheck the said CheckBox more conveniently.
You should use MVVM instead. Walking down the VisualTree is a really hacky workaround.
I'm trying to get the datagrid's scrollviewer to be able to set the offset (which has been stored earlier).
I use this function :
public static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
And I call it like this :
this.dataGrid.ItemsSource = _myData;
ScrollViewer sc = ressource_design.GetVisualChild<ScrollViewer>(this.dataGrid);
if (sc != null) sc.ScrollToVerticalOffset(stateDatagrid.ScrollbarOffset);
And it works in many cases, but in some cases the function returns null and I'm not able to get the scrollviewer.
This call is made just after setting the ItemsSource (ObservableCollection of items) and it works well in 90% cases. The datagrid has not been rendered yet.
I've also tried with the function :
public static ScrollViewer GetScrollViewerFromDataGrid(DataGrid dataGrid)
{
ScrollViewer retour = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dataGrid) && retour == null; i++)
{
if (VisualTreeHelper.GetChild(dataGrid, i) is ScrollViewer)
{
retour = (ScrollViewer)(VisualTreeHelper.GetChild(dataGrid, i));
}
}
return retour;
}
still null.
Why I'm unable to get the datagrid's scrollviewer ?
I've not pasted my datagrid's style since I have datagrids working with it and it is complicated with many dependencies.
I thought it could be related to virtualization but i'm not able to retrieve the scrollviewer of this datagrid :
<DataGrid Style="{StaticResource StyleDataGrid}" HeadersVisibility="None" ItemsSource="{Binding _Data}" Name="dataGrid1" RowDetailsVisibilityMode="Visible" SelectionChanged="dataGrid1_SelectionChanged">
You need to go recursive through the VisualTree elements. Your function only looks at DataGrid layer. If the ScrollViewer isn't there (see picture) you will not find it.
Try the following function:
public static ScrollViewer GetScrollViewer(UIElement element)
{
if (element == null) return null;
ScrollViewer retour = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element) && retour == null; i++) {
if (VisualTreeHelper.GetChild(element, i) is ScrollViewer) {
retour = (ScrollViewer) (VisualTreeHelper.GetChild(element, i));
}
else {
retour = GetScrollViewer(VisualTreeHelper.GetChild(element, i) as UIElement);
}
}
return retour;
}
How can I access the ItemsPanel of a ListBox at runtime in silverlight?
Given the following element declaration in XAML
<ListBox x:Name="LB" Loaded="LB_Loaded" />
There are two ways to achieve this, the easiest requires the Silverlight toolkit:
using System.Windows.Controls.Primitives;
private void LB_Loaded()
{
var itemsPanel = LB.GetVisualChildren().OfType<Panel>().FirstOrDefault();
}
Or you can use the VisualTreeHelper and write the following recursive method:
T GetFirstChildOfType<T>(DependencyObject visual) where T:DependencyObject
{
var itemCount = VisualTreeHelper.GetChildrenCount(visual);
if (itemCount < 1)
{
return null;
}
for (int i = 0; i < itemCount; i++)
{
var dp = VisualTreeHelper.GetChild(visual, i);
if (dp is T)
{
return (T)dp;
}
}
for (int i = 0; i < itemCount; i++)
{
var dp = GetFirstChildOfType<T>(VisualTreeHelper.GetChild(visual, i));
if (dp != null) return dp;
}
return null;
}
And get the result in a similar manner:
void ItemsPanelSample_Loaded(object sender, RoutedEventArgs e)
{
var itemsPanel = GetFirstChildOfType<Panel>(LB);
}
Building on terphi's solution, i changed it to return a list of the elements you are looking for as normally when your searching for a type, the listbox will have multiple items and multiple instances of what you are looking for. Additionally, I had issues with it finding things in the loaded event but used a dispatcher instead and it finds the items every time in testing.
private List<TextBlock> TextBlockList;
in the constructor, after associating the datasource with listbox:
Dispatcher.BeginInvoke(delegate { TextBlockList = GetFirstChildOfType<TextBlock>(listBox1); });
List<T> GetFirstChildOfType<T>(DependencyObject visual) where T : DependencyObject
{
DependencyObject ControlCandidate;
List<T> TempElements;
List<T> TargetElementList = new List<T>();
var itemCount = VisualTreeHelper.GetChildrenCount(visual);
if (itemCount > 0)
{
for (int i = 0; i < itemCount; i++)
{
ControlCandidate = VisualTreeHelper.GetChild(visual, i);
if (ControlCandidate is T)
TargetElementList.Add((T)ControlCandidate);
}
for (int i = 0; i < itemCount; i++)
{
TempElements = GetFirstChildOfType<T>(VisualTreeHelper.GetChild(visual, i));
if (TempElements.Count > 0)
TargetElementList.AddRange(TempElements);
}
}
return TargetElementList;
}
How do I loop through the all controls in a window in WPF?
I found this in the MSDN documenation so it helps.
// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
{
// Retrieve child visual at specified index value.
Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
// Do processing of the child visual object.
// Enumerate children of the child visual object.
EnumVisual(childVisual);
}
}
Looks simpler to me. I used it to find textboxes in a form and clear their data.
This way is superior to the MSDN method, in that it's reusable, and it allows early aborting of the loop (i.e. via, break;, etc.) -- it optimizes the for loop in that it saves a method call for each iteration -- and it also lets you use regular for loops to loop through a Visual's children, or even recurse it's children and it's grand children -- so it's much simpler to consume.
To consume it, you can just write a regular foreach loop (or even use LINQ):
foreach (var ctrl in myWindow.GetChildren())
{
// Process children here!
}
Or if you don't want to recurse:
foreach (var ctrl in myWindow.GetChildren(false))
{
// Process children here!
}
To make it work, you just need put this extension method into any static class, and then you'll be able to write code like the above anytime you like:
public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true)
{
if (parent != null)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
// Retrieve child visual at specified index value.
var child = VisualTreeHelper.GetChild(parent, i) as Visual;
if (child != null)
{
yield return child;
if (recurse)
{
foreach (var grandChild in child.GetChildren(true))
{
yield return grandChild;
}
}
}
}
}
}
Also, if you don't like recursion being on by default, you can change the extension method's declaration to have recurse = false be the default behavior.
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);
}
}
}
}
I've used the following to get all controls.
public static IList<Control> GetControls(this DependencyObject parent)
{
var result = new List<Control>();
for (int x = 0; x < VisualTreeHelper.GetChildrenCount(parent); x++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, x);
var instance = child as Control;
if (null != instance)
result.Add(instance);
result.AddRange(child.GetControls());
}
return result;
}
A slight variation on the MSDN answer ... just pass in an empty List of Visual objects into it and your collection will be populated with all the child visuals:
/// <summary>
/// Enumerate all the descendants (children) of a visual object.
/// </summary>
/// <param name="parent">Starting visual (parent).</param>
/// <param name="collection">Collection, into which is placed all of the descendant visuals.</param>
public static void EnumVisual(Visual parent, List<Visual> collection)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
// Get the child visual at specified index value.
Visual childVisual = (Visual)VisualTreeHelper.GetChild(parent, i);
// Add the child visual object to the collection.
collection.Add(childVisual);
// Recursively enumerate children of the child visual object.
EnumVisual(childVisual, collection);
}
}
The previous answers will all return the children that are identified by VisualTreeHelper.GetChildrenCount and VisualTreeHelper.GetChild. However, I have found that for a TabControl, the TabItems and their content are not identified as children. Thus, these would be omitted, and I think the original question ("all controls in a window") would like to have them included.
To properly loop through tabbed controls as well, you will need something like this (modified from the answer of #BrainSlugs83):
public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true)
{
if (parent != null)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
// Retrieve child visual at specified index value.
var child = VisualTreeHelper.GetChild(parent, i) as Visual;
if (child != null)
{
yield return child;
if (recurse)
{
foreach (var grandChild in child.GetChildren(true))
{
yield return grandChild;
}
// Tabs and their content are not picked up as visual children
if (child is TabControl childTab)
{
foreach (var childTabItem in childTab.Items)
{
yield return childTabItem;
foreach (var childTabItemChild in childTabItem.GetChildren(true))
{
yield return childTabItemChild;
}
if (childTabItem.Content != null && childTabItem.Content is Visual childTabItemContentAsVisual)
{
yield return childTabItemContentAsVisual;
foreach (var childTabItemGrandChild in childTabItemContentAsVisual.Children(true)
{
yield return childTabItemGrandChild;
}
}
}
}
}
}
}
}
}
Alternatively, you could iterate over the logical tree instead of the visual tree:
public static IEnumerable<DependencyObject> GetLogicalChildren(this DependencyObject parent, bool recurse = true)
{
if (parent == null) yield break;
foreach (var child in LogicalTreeHelper.GetChildren(parent).OfType<DependencyObject>())
{
yield return child;
if (recurse)
{
foreach (var grandChild in child.GetLogicalChildren(true))
{
yield return grandChild;
}
}
}
}
I tried it myself and I found an elegant solution that also works in any scenario, not like all the solutions posted here that are overengineered and broken. The majority of the answers here are over-engineered and unstable.
The idea is to loop through a parent control in Windows Presentation Foundation to get the children controls of the desired type or types.
First you need a loop that has an integer, set to zero preferably, with the use of indexing and a VisualTreeHelper object that is counting all the objects within the parent control as the loop's condition.
for(int ControlCounter = 0; ControlCounter <= VisualTreeHelper.GetChildrenCount(MaterialsContentComputerSystemsFoundationYear) - 1; ControlCounter++)
{
if(VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter).GetType() == File1.GetType())
{
Button b = (Button)VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter);
if (ActualButtonControlIndex == App.FileIndex[ActualButtonControlIndex])
{
}
else
{
b.Visibility = Visibility.Hidden;
}
ActualButtonControlIndex++;
System.Diagnostics.Debug.WriteLine(ActualButtonControlIndex + " Button");
}
}
Within the for loop you can make a conditional statement that is verifying if the type of the current control at the current index is equal with the type of control that is desired. In this example I used a control that is named and is part of the desired type of control that is currently searched. You can use a variable that is storing a button instead, for type comparison.
var b = new Button();
for(int ControlCounter = 0; ControlCounter <= VisualTreeHelper.GetChildrenCount(MaterialsContentComputerSystemsFoundationYear) - 1; ControlCounter++)
{
if(VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter).GetType() == b.GetType())
{
Button B = (Button)VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter);
if (ActualButtonControlIndex == App.FileIndex[ActualButtonControlIndex])
{
}
else
{
B.Visibility = Visibility.Hidden;
}
ActualButtonControlIndex++;
System.Diagnostics.Debug.WriteLine(ActualButtonControlIndex + " Button");
}
}
Within the for loop's conditional statement, an object of the type of the desired control is created that has its value set with the value of the VisualTreeHelper object at the current index casted to the type Button.
You can use the previously mentioned button to set proprieties like size, with and content, colour, etc. to the control in the application's window, within the parent control within that window, at the current index.
var b = new Button();
for(int ControlCounter = 0; ControlCounter <= VisualTreeHelper.GetChildrenCount(MaterialsContentComputerSystemsFoundationYear) - 1; ControlCounter++)
{
if(VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter).GetType() == b.GetType())
{
Button B = (Button)VisualTreeHelper.GetChild(MaterialsContentComputerSystemsFoundationYear, ControlCounter);
if (ActualButtonControlIndex == App.FileIndex[ActualButtonControlIndex])
{
B.Content = "Hello";
B.FontSize = 20;
B.BackGround = new SolidColorBrush(Colors.Red);
}
else
{
B.Visibility = Visibility.Hidden;
}
ActualButtonControlIndex++;
System.Diagnostics.Debug.WriteLine(ActualButtonControlIndex + " Button");
}
}
This solution is modular, simple and super-stable and thus useful in any scenario, give a like.