如何在代码后面获取ListBox ItemsPanel

发布于 2024-12-03 07:33:41 字数 635 浏览 2 评论 0原文

我有一个带有 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 一起使用

谢谢

I have a ListBox with an ItemsPanel

<Setter Property="ItemsPanel">
    <Setter.Value>
        <ItemsPanelTemplate>
             <StackPanel x:Name="ThumbListStack" Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </Setter.Value>
</Setter>

I am wanting to move the Stack Panel along the X-axis using a TranslateTransform in code behind.

Problem is, I can't find the Stack Panel.

ThumbListBox.FindName("ThumbListStack")

Returns nothing.
I want to use it in:

Storyboard.SetTarget(x, ThumbListBox.FindName("ThumbListStack"))

How do I get the Stack Panel so I can then use it with the TranslateTransform

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

榕城若虚 2024-12-10 07:33:41

您可以使用 ItemsPanelTemplate 中的 StackPanelLoaded 事件

<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;
}

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;
}
茶色山野 2024-12-10 07:33:41

抱歉,我刚刚注意到我忘记保存编辑...我意识到您已经接受了答案,但对我来说这似乎更像是一种黑客行为。这是我对 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);

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);
诗酒趁年少 2024-12-10 07:33:41

尝试以下扩展方法:

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: 您可以自己扩展它以检查特定的控件名称,以便方法将返回单个控件而不是列表。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文