Cómo obtener el cuadro de lista de listboxpanel en código detrás
-
27-10-2019 - |
Pregunta
Tengo un cuadro de lista con un elementopanel
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
Quiero mover el panel de pila a lo largo del eje X utilizando una transformación tradicional en código detrás.
El problema es que no puedo encontrar el panel de pila.
ThumbListBox.FindName("ThumbListStack")
No devuelve nada. Quiero usarlo en:
Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))
¿Cómo obtengo el panel de pila para que pueda usarlo con la transformación?
Gracias
Solución
Puedes usar el Loaded
evento para el StackPanel
que esta en el 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>
Y luego en código detrás
private StackPanel m_itemsPanelStackPanel;
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
m_itemsPanelStackPanel = sender as StackPanel;
}
Otra forma es atravesar el árbol visual y encontrar el StackPanel
¿Cuál será el primer hijo del 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;
}
Otros consejos
Lo siento, acabo de notar que olvidé guardar la edición ... Me doy cuenta de que ya ha aceptado una respuesta, pero me parece más un truco. Aquí está mi implementación de Findchild, es posible que desee usarlo para el futuro o si va a hacer esto a menudo.
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;
}
Verifica a todos los niños y los niños de los niños que comparan el tipo y el nombre establecido en el control. Úselo así:
StackPanel ipanel = ThumbListBox.FindChild<StackPanel>("ThumbListStack");
if(ipanel == null)
MessageBox.Show("couldn't find anything");
else
MessageBox.Show("Aha! Found: " ipanel.Name);
Pruebe el método de extensión de siguientes:
var childStackPanels = FindVisualChildren<StackPanel>(ThumbListBox);
Método en sí:
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;
}
}
}
}
PD: Puede extenderlo para verificar el nombre de control específico para que el método devuelva el control único en lugar de la lista.