Comment LISTBOX ItemsPanel dans le code derrière
-
27-10-2019 - |
Question
J'ai un ListBox avec un ItemsPanel
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
Je suis désireux de déplacer le panneau pile le long de l'axe X utilisant un TranslateTransform dans le code derrière.
Le problème est, je ne peux pas trouver le panneau de la pile.
ThumbListBox.FindName("ThumbListStack")
ne renvoie rien. Je veux l'utiliser dans:
Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))
Comment puis-je obtenir le panneau de la pile pour que je puisse ensuite l'utiliser avec le TranslateTransform
Merci
La solution
Vous pouvez utiliser l'événement pour la Loaded
StackPanel
qui est dans le 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>
Et puis dans le code derrière
private StackPanel m_itemsPanelStackPanel;
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
m_itemsPanelStackPanel = sender as StackPanel;
}
Une autre façon est de parcourir l'arborescence visuelle et trouver le StackPanel
qui sera le premier enfant du 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;
}
Autres conseils
désolé, je viens de remarquer que j'oublié de sauvegarder le modifier ... Je sais que vous avez déjà accepté une réponse, mais il semble plus d'un hack pour moi. Voici ma mise en œuvre de FindChild, vous pouvez l'utiliser pour l'avenir ou si vous allez faire souvent.
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;
}
Il vérifie tous les enfants et les enfants des enfants comparant le type et ensemble Nom sur le contrôle. Utilisez comme ceci:
StackPanel ipanel = ThumbListBox.FindChild<StackPanel>("ThumbListStack");
if(ipanel == null)
MessageBox.Show("couldn't find anything");
else
MessageBox.Show("Aha! Found: " ipanel.Name);
Essayez la méthode suivante d'extension:
var childStackPanels = FindVisualChildren<StackPanel>(ThumbListBox);
Méthode elle-même:
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:. Vous pouvez vous étendre pour vérifier le nom de contrôle spécifique si la méthode retournerait contrôle unique au lieu de la liste