Как получить ListBox ItemsPanel в коде
У меня есть ListBox с ItemsPanel
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
Я хочу переместить панель стека по оси X, используя код TranslateTransform в коде.
Проблема в том, что я не могу найти панель стека.
ThumbListBox.FindName("ThumbListStack")
Возвращает ничего.
Я хочу использовать его в:
Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))
Как получить панель стека, чтобы затем использовать ее с помощью TranslateTransform
Спасибо
Ответы
Ответ 1
Вы можете использовать событие Loaded
для StackPanel
, которое находится в 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>
И затем в коде
private StackPanel m_itemsPanelStackPanel;
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
m_itemsPanelStackPanel = sender as StackPanel;
}
Другой способ - пересечь визуальное дерево и найти StackPanel
, который будет первым дочерним элементом 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;
}
Ответ 2
Извините, я только что заметил, что забыл сохранить редактирование... Я понимаю, что вы уже приняли ответ, но мне кажется, что это больше для меня. Здесь моя реализация FindChild, вы можете использовать ее в будущем или если вы будете делать это часто.
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;
}
Он проверяет все дочерние и дочерние дети, сравнивая тип и имя, установленные в элементе управления. Используйте его так:
StackPanel ipanel = ThumbListBox.FindChild<StackPanel>("ThumbListStack");
if(ipanel == null)
MessageBox.Show("couldn't find anything");
else
MessageBox.Show("Aha! Found: " ipanel.Name);
Ответ 3
Попробуйте следующий метод расширения:
var childStackPanels = FindVisualChildren<StackPanel>(ThumbListBox);
Сам метод:
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: Вы можете продлить его, чтобы проверить конкретное имя управления, чтобы метод возвращал единый элемент управления вместо списка.