添加到ItemsControl的项目没有使用ItemTemplate

本文关键字:ItemTemplate 项目 ItemsControl 添加 | 更新日期: 2023-09-27 18:13:30

我对wpf比较陌生,所以我提前为任何不好的编码习惯道歉。

我正在尝试创建一个仪表板应用程序,用户可以通过添加不同的控件(表,图等)并移动它们周围/调整它们的大小。

我最初使用画布来绘制我的控件,并有移动和调整大小的工作。由于需要内容是动态的,我切换到使用ItemsControl,如下所示:

<ItemsControl Name="dashboardCanvas" ItemsSource="{Binding Path=CanvasContents}" Grid.Row="1">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.Resources>
            <ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type local:MoveThumb}">
                <Rectangle Fill="Transparent"/>
            </ControlTemplate>
            <ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="Control">
                <Grid>
                    <local:ResizeThumb Height="2" Cursor="SizeNS" Margin="0 -4 0 0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
                    <local:ResizeThumb Width="2" Cursor="SizeWE" Margin="-4 0 0 0" VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
                    <local:ResizeThumb Width="2" Cursor="SizeWE" Margin="0 0 -4 0" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
                    <local:ResizeThumb Height="2" Cursor="SizeNS" Margin="0 0 0 -4" VerticalAlignment="Bottom"  HorizontalAlignment="Stretch"/>
                    <local:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
                    <local:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
                    <local:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
                    <local:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
                </Grid>
            </ControlTemplate>
            <ControlTemplate x:Key="DesignerItemTemplate">
                <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                    <local:MoveThumb Template="{StaticResource MoveThumbTemplate}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Cursor="SizeAll"/>
                    <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
                    <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
                    <Button Content="x" VerticalAlignment="Top" HorizontalAlignment="Right" Width="10" Height="10" Click="Button_Click"/>
                </Grid>
            </ControlTemplate>
        </ItemsControl.Resources>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                    <local:MoveThumb Template="{StaticResource MoveThumbTemplate}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Cursor="SizeAll"/>
                    <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
                    <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
                    <Button Content="x" VerticalAlignment="Top" HorizontalAlignment="Right" Width="10" Height="10" Click="Button_Click"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
                <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>

我现在有一个问题,我添加到ItemsControl的任何控件都没有模板应用到它们。

我看到过这个问题:为什么ItemsControl不使用我的ItemTemplate?但是我不能将ItemsControl继承到我的控件中,因为它们已经继承了ContentControls。

这是我的主要控制对象:

class TableControl: DashboardItem
{
    public TableControl()
    {
        Width = 100;
        Height = 100;
        Content = new Ellipse
            {
                Fill = new SolidColorBrush(Colors.Green),
                IsHitTestVisible = false
            };
    }
    public int X
    {
        get
        {
            return 10;
        }
    }
    public int Y
    {
        get
        {
            return 200;
        }
    }
}

DashboardItem现在只是:

class DashboardItem : ContentControl
{
}

在后面的代码中,我有一个DashboardItems的ObservableCollection, ItemsControl被绑定到。

我如何强制ItemsControl模板应用于控件中的所有项?

添加到ItemsControl的项目没有使用ItemTemplate

您的代码中有奇怪的混合。不能有ContentControlObservableCollection。让你的对象DashboardItems,真正的业务对象(或视图模型对象),可以持有X和Y属性,但不继承ContentControl

如果你提供一个GUI对象,WPF似乎并不关心你的模板。

如果你需要为items控件的不同项目设置不同的外观,那么你可以使用
-a TemplateSelector(用于为给定行选择模板)
-或DataItemTemplate的DataType属性

再加一个解。正如公认的答案所指出的那样,如果您直接使用ItemsControl,那么您传入的任何GUI对象都将按原样排列在ItemsPanel上,从而完全绕过DataTemplate。(如果它不是一个GUI对象,它首先被包装在ContentPresenter中。)

为了解决这个问题,您可以创建ItemsControl的一个子类,强制它总是为您的项目创建一个容器。为此,可以为IsItemItsOwnContainerOverride返回false。这告诉控件项必须首先包装在容器中——同样,在ItemsControl的默认实现中是一个简单的ContentPresenter——因此它将始终应用任何给定的ItemTemplate

代码如下:

public class EnsureContainerItemsControl : ItemsControl {
    protected override bool IsItemItsOwnContainerOverride(object item) {
        return false; // Force the control to always generate a container regardless of what was passed in
    }
}