ContentPresenter 而不是 UserControl 添加到我的自定义面板

ContentPresenter instead of UserControl is added to my custom panel

我创建了一个继承自 Canvas 的自定义面板。我想用它来查看我在 ItemsControl 中的用户控件。

这是我的 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>

如您所见,我的用户控件将 MinWidth 设置为 200。

现在,在我的自定义面板中覆盖了 ArrangeOverride 方法:

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

问题是,出于某种原因,InternalChildren 包含 ContentPresenter 项而不是我的用户控件。当然,在每个 ContentPresenter 中都有我的用户控件,但这不是我想要的。我需要在此处读取我的 userControl 的 MinWidth,但我从 ContentPresenter(始终为 0)读取它。

当我做非常简单的测试时:

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

其中 Buttons 只是 Button 控件的列表,一切都按预期工作。所以我认为问题可能出在我使用 ItemsControl 的方式上。但是不知道怎么修复。

在 ItemContainerStyle 中设置 ContentPresenter 的 MinWidth 属性:

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

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

这是因为 ItemsControl 将所有项目包装在 ContentPresenter 中,除非它们是 UIElements。如果您绑定到 UIElements 的集合,例如 Buttons,则不会创建 ContentPresenter,但也不会应用 ItemTemplate

您可以按照@Clemens 的建议设置 ContentPresenter 容器的 MinWidth,或者您可以通过实现自己的自定义 [=11] 来阻止创建 ContentPresenters =] 并覆盖 GetContainerForItemOverride()IsItemItsOwnContainerOverride() 方法:

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

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