How to set all Controls in wpf to unfocusable? - c#

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;
}

Related

Get datagrid's scrollviewer

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 to get instance of ItemsPanel?

I'm writing custom control where I switch default ItemsPanel with
ItemsPanelProperty.OverrideMetadata(typeof(DataGrid),
new FrameworkPropertyMetadata(new ItemsPanelTemplate(
new FrameworkElementFactory(typeof(AdvancedVirtualizingStackPanel)))));
How can I get reference to the instance of created AdvancedVirtualizingStackPanel?
Ok, I will answer myself.
First you need to get ItemsPresenter. You can use this code:
ItemsPresenter itemsPresenter =
(ItemsPresenter)GetTemplateChild(ItemsPresenterTemplateName);
// You have to name ItemsPresenter (using value of
// ItemsPresenterTemplateName string) in your XAML
Then:
itemsPresenter.ApplyTemplate(); // In case template is not applied yet
_stackPanel =
Helper.GetVisualChild<AdvancedVirtualizingStackPanel>(itemsPresenter);
And you got your panel.
Code for Helper.GetVisualChild():
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;
}

How can I remove specified pushpins?

I add pushpins dynamically to a Bing map. I also want to remove certain ones (based on a value embedded in their Tag property). In order to do this, do I need to identify the pushpin's MapOverlay, and if so, how might I go about that?
I am not sure which environment you are talking about, but it looks like its not windows 8.
So here is some code for windows phone 7.1. This assumes that you only have Pushpins in your map's children collection. If you also have other UI elements you would have to filter those out before going for the Tag property ;)
Pushpin t1 = new Pushpin();
t1.Tag = "t1";
map1.Children.Add(t1);
Pushpin t2 = new Pushpin();
t2.Tag = "t2";
map1.Children.Add(t2);
Pushpin t3 = new Pushpin();
t3.Tag = "t3";
map1.Children.Add(t3);
// LINQ query syntax
var ps = from p in map1.Children
where ((string)((Pushpin)p).Tag) == "t1"
select p;
var psa= ps.ToArray();
for (int i = 0; i < psa.Count();i++ )
{
map1.Children.Remove(psa[i]);
}
// or using method syntax
var psa2= map1.Children.Where(y => ((string)((Pushpin)y).Tag) == "t2").ToArray();
for (int i = 0; i < psa2.Count(); i++)
{
map1.Children.Remove(psa2[i]);
}
The map1 is defined in the apps main page; XAML like this:
<my:Map HorizontalAlignment="Stretch" Name="map1" VerticalAlignment="Stretch" />
I think this might work:
var pushPins = SOs_Classes.SOs_Utils.FindVisualChildren<Pushpin>(bingMap);
foreach (var pushPin in pushPins)
{
if (pushPin.Tag is SOs_Locations)
{
SOs_Locations locs = (SOs_Locations) pushPin.Tag;
if (locs.GroupName == groupToAddOrRemove)
{
bingMap.Children.Remove(pushPin);
}
}
}
// I got this from somebody somewhere, but forgot to note who/where
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null)
{
yield break;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (var childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}

How to get ListBox ItemsPanel in code behind

I have a ListBox with an ItemsPanel
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
I am wanting to move the Stack Panel along the X-axis using a TranslateTransform in code behind.
Problem is, I can't find the Stack Panel.
ThumbListBox.FindName("ThumbListStack")
Returns nothing.
I want to use it in:
Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))
How do I get the Stack Panel so I can then use it with the TranslateTransform
Thanks
You can use the Loaded event for the StackPanel that is in the ItemsPanelTemplate
<Grid>
<Grid.Resources>
<Style TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal"
Loaded="StackPanel_Loaded" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ListBox />
</Grid>
And then in code behind
private StackPanel m_itemsPanelStackPanel;
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
m_itemsPanelStackPanel = sender as StackPanel;
}
Another way is to traverse the Visual Tree and find the StackPanel which will be the first child of the ItemsPresenter.
public void SomeMethod()
{
ItemsPresenter itemsPresenter = GetVisualChild<ItemsPresenter>(listBox);
StackPanel itemsPanelStackPanel = GetVisualChild<StackPanel>(itemsPresenter);
}
private 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;
}
sorry I just noticed I forgot to save the edit...I realize you've already accepted an answer, but it seems more of a hack to me. Here's my implementation of FindChild, you might want to use it for the future or if you're going to be doing this often.
public static T FindChild<T>(this FrameworkElement obj, string name)
{
DependencyObject dep = obj as DependencyObject;
T ret = default(T);
if (dep != null)
{
int childcount = VisualTreeHelper.GetChildrenCount(dep);
for (int i = 0; i < childcount; i++)
{
DependencyObject childDep = VisualTreeHelper.GetChild(dep, i);
FrameworkElement child = childDep as FrameworkElement;
if (child.GetType() == typeof(T) && child.Name == name)
{
ret = (T)Convert.ChangeType(child, typeof(T));
break;
}
ret = child.FindChild<T>(name);
if (ret != null)
break;
}
}
return ret;
}
It checks all the children and the children's children comparing the type and Name set on the control. Use it like this:
StackPanel ipanel = ThumbListBox.FindChild<StackPanel>("ThumbListStack");
if(ipanel == null)
MessageBox.Show("couldn't find anything");
else
MessageBox.Show("Aha! Found: " ipanel.Name);
Try out following extension method:
var childStackPanels = FindVisualChildren<StackPanel>(ThumbListBox);
Method itself:
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
var typedChild = child as T;
if (typedChild != null)
{
yield return typedChild;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
PS: You can yourself extend it to check for specific control name so method would return single control instead of list.

WPF: How do I loop through the all controls in a window?

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.

Categories

Resources