How to get ListBox ItemsPanel in code behind
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.