Search code examples
wpftemplatescontrolscode-behindcontentpresenter

How do I access a named Control within my ItemPanelTemplate from the code-behind?


I am trying to access a Canvas object within an ItemsPanelTemplate so I can add items directly to it in the code-behind.

Here is my XAML:

 <ListBox x:Name="MyMap" ItemsSource="{Binding MapItems}" 
        Background="Gray"
        SelectionChanged="MyMap_SelectionChanged">

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas x:Name="MyMapCanvas"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Background="Transparent">
            </Canvas>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

How can I access "MyMapCanvas" in the code-behind to add items to it?

I have tried the following:

Canvas canvas = (Canvas)MyMap.ItemsPanel.LoadContent();

and

ContentPresenter cp = (ContentPresenter)(VisualTreeHelper.GetChild(MyMap, 0));
ItemsPanelTemplate ipt = MyMap.ItemsPanel;
Canvas canvas = ipt.FindName("MyMapCanvas", cp) as Canvas;

Thanks in advance.


Solution

  • Try this:

        //your OnLoaded handler
        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            Canvas canvas = FindVisualChild<Canvas>(MyMap);
        }
    
        public TChildItem FindVisualChild<TChildItem>(DependencyObject obj) where TChildItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                var child = VisualTreeHelper.GetChild(obj, i);
    
                if (child != null && child is TChildItem)
                    return (TChildItem)child;
    
                var childOfChild = FindVisualChild<TChildItem>(child);
    
                if (childOfChild != null)
                    return childOfChild;
            }
    
            return null;
        }