添加到ItemsControl的项目不使用ItemTemplate

时间:2015-09-18 08:49:47

标签: c# .net wpf data-binding

我对wpf比较新,所以我提前为任何糟糕的编码做法道歉。

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

我最初使用Canvas来绘制我的控件并进行移动和调整大小的工作。由于需要内容是动态的,我转而使用如下的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的任何控件都没有应用模板。

我已经看到了这个问题:Why Does ItemsControl Not Use My 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模板应用于控件中的所有项目?

2 个答案:

答案 0 :(得分:1)

Blinx,

我尝试了你的代码,发现了这个错误。

您的代码中存在奇怪的混合。 您的ObservableCollection ContentControl不得为DashboardItems。 使您的对象ContentControl,真实业务对象(或viewmodel对象)可能持有X和Y属性,但没有typecast的继承。

如果您提供GUI对象,似乎WPF不关心您的模板。

如果您需要为Items Control的不同项目提供不同的外观,那么您将能够使用
-a TemplateSelector(用于为给定行选择模板)
- 或DataItemTemplate的DataType属性

祝你好运

答案 1 :(得分:0)

只需添加另一个解决方案。正如公认的答案所指出的,如果直接使用ItemsControl,则传入的任何GUI对象都将按原样排列在ItemsPanel上,从而完全绕开DataTemplate。 (如果不是GUI对象,则首先将其包装在ContentPresenter中。)

要解决此问题,可以创建ItemsControl的子类,您必须强制始终为项目创建一个容器。您可以通过将false返回IsItemItsOwnContainerOverride来完成此操作。这告诉控件该项目必须先包装在容器中-再次,在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
    }
}