如何在后面的代码中获取 ListBox ItemsPanel
Posted
技术标签:
【中文标题】如何在后面的代码中获取 ListBox ItemsPanel【英文标题】:How to get ListBox ItemsPanel in code behind 【发布时间】:2011-11-11 07:22:43 【问题描述】:我有一个带有 ItemsPanel 的 ListBox
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
我想在后面的代码中使用 TranslateTransform 沿 X 轴移动堆栈面板。
问题是,我找不到堆栈面板。
ThumbListBox.FindName("ThumbListStack")
什么都不返回。 我想用在:
Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))
我如何获得堆栈面板,以便我可以将它与 TranslateTransform 一起使用
谢谢
【问题讨论】:
如果这只是一个ListBox
,您可以将Loaded
事件用于StackPanel
,然后将其存储在后面的代码中
嗨,Meleak,我如何附加到 StackPanel 的 Loaded 事件?我在 VS 中看不到它是一个选项
我添加了一个关于如何使用Loaded
事件的答案,如果您的样式定义在与Listbox
相同的视图中,该事件将起作用。否则,您可以使用我的答案的第二部分搜索可视树
【参考方案1】:
抱歉,我刚刚注意到我忘记保存编辑了...我意识到您已经接受了答案,但对我来说这似乎更像是一种黑客行为。这是我对 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);
【讨论】:
嗨,萨阿德,感谢您的回复。我还处于 WPF 的早期阶段,但我对 FindParent 的解释是它会上树,而不是下树。 ItemsPanel 不是在树下吗?即 StackPanel 是 ThumbListBox 的子项? 嘿本,对不起,我第一次误解了。没错,StackPanel 是 ThumbListBox 的子项。我更新了我的答案。 嗨,Saad,我看不到您的回答有任何变化? @Ben 嘿,对不起。我忘了保存我的编辑。我现在保存了它,您可能仍想使用它,或者将来可能会使用它。【参考方案2】:尝试以下扩展方法:
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:您可以自己扩展它以检查特定的控件名称,因此方法将返回单个控件而不是列表。
【讨论】:
【参考方案3】:您可以将Loaded
事件用于ItemsPanelTemplate
中的StackPanel
<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;
【讨论】:
最好将 GetVisualChild() 重命名为 GetFirstVisualChild() @Ben:很高兴听到它奏效了,很高兴为您提供帮助 :) 您知道,现在您的声誉得分超过 15,您可以投票赞成您认为有帮助的答案。 这也可以在Initialized 事件处理程序中完成。然后,成员变量将在初始化阶段设置并且已经有效,例如当引发父控件或窗口的 Loaded 事件时。以上是关于如何在后面的代码中获取 ListBox ItemsPanel的主要内容,如果未能解决你的问题,请参考以下文章
c# winform listbox 如何 获取 当前 选中的值 急!!!