How to get ListBox ItemsPanel in code behind

后端 未结 3 886
心在旅途
心在旅途 2020-12-17 16:20

I have a ListBox with an ItemsPanel


    
        
             

        
相关标签:
3条回答
  • 2020-12-17 16:40

    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);
    
    0 讨论(0)
  • 2020-12-17 16:55

    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;
    }
    
    0 讨论(0)
  • 2020-12-17 16:55

    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.

    0 讨论(0)
提交回复
热议问题