Adam Jachocki
Adam Jachocki

Reputation: 2125

ContentPresenter instead of UserControl is added to my custom panel

I have created a custom panel inherited from Canvas. I would like to use it to view my user controls in ItemsControl.

This is my XAML:

<ItemsControl ItemsSource="{Binding Groups}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <c:MyCustomPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <ItemContainerTemplate>
                <app:MyUserControl Margin="5" MinWidth="200"/>                    
            </ItemContainerTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

As you can see, my user control has MinWidth set to 200.

Now, in my custom panel there is ArrangeOverride method overriden:

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        foreach (UIElement obj in InternalChildren)
        {
           //some other code   
        }
        return arrangeSize;
    }

The problem is that for some reason InternalChildren consist of ContentPresenter items instead of my user controls. In every ContentPresenter there is my user control of course, but this is not what I would like to be. I need to read here the MinWidth of my userControl, but instead I read it from ContentPresenter (which is always 0).

When I do very simple test:

<ItemsControl ItemsSource="{Binding Buttons}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <c:MyCustomPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

where Buttons is just list of Button controls, everything works as expected. So I think that the problem may be somewhere in how I use ItemsControl. But don't have any idea how to repair it.

Upvotes: 0

Views: 165

Answers (2)

Clemens
Clemens

Reputation: 128061

Set the MinWidth property of the ContentPresenter in an ItemContainerStyle:

<ItemsControl ItemsSource="{Binding Groups}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <c:MyCustomPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <app:MyUserControl Margin="5"/>                    
        </DataTemplate>
    </ItemsControl.ItemTemplate>

    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="MinWidth" Value="200"/>                    
        </Style >
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

Upvotes: 1

mm8
mm8

Reputation: 169200

The problem is that for some reason InternalChildren consist of ContentPresenter items instead of my user controls.

This is because the ItemsControl wraps all items in a ContentPresenter unless they are UIElements. If you bind to a collection of UIElements, like for example Buttons, there is no ContentPresenter created but there is also no ItemTemplate applied.

You could either set the MinWidth of the ContentPresenter containers as suggested by @Clemens, or you could prevent the ContentPresenters from getting created by implementing your own custom ItemsControl and override the GetContainerForItemOverride() and IsItemItsOwnContainerOverride() methods:

public class MyItemsControl : System.Windows.Controls.ItemsControl
{
    protected virtual DependencyObject GetContainerForItemOverride()
    {
        return new MyUserControl();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is MyUserControl);
    }
}

Upvotes: 1

Related Questions