创建使用datatemplates的WPF控件

时间:2016-11-05 17:15:36

标签: wpf vb.net custom-controls datatemplate

我正在尝试构建一个控件,该控件将在一个调度网格中显示项目,以便根据它们的类别水平放置它们,并根据它们的计划时间和垂直时间垂直放置该项目将完成。我目前继承自System.Windows.Controls.Control,默认样式和模板如下所示:

    <Style TargetType="KHS:TimeGrid">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="KHS:TimeGrid">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
                            <DockPanel>
                                <Grid Name="PART_HeaderGrid" DockPanel.Dock="Top">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="{Binding ActualWidth, ElementName=TimeColumn}"/>
                                    </Grid.ColumnDefinitions>
                                </Grid>

                                <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
                                    <Grid Name="PART_BodyGrid">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Name="TimeColumn" Width="Auto"/>
                                        </Grid.ColumnDefinitions>
                                    </Grid>
                                </ScrollViewer>
                            </DockPanel>
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

对于我的项目,我只是使用这个界面:

Public Interface ITimeGridItem
    Property StartTime As Date
    Property Duration As TimeSpan
End Interface

将行添加到&#34; BodyGrid&#34;对于每个时间增量(默认表示15分钟),项目根据其开始时间和持续时间给出Grid.Row和Grid.RowSpan值。

当我尝试为项目实现DataTemplates时,我遇到了问题。我目前正在尝试使用ContentPresenters来显示这些项目。为TimeGrid创建一个ItemTemplate属性会很容易,只是将它用于所有项目,但是如果我需要使用唯一模板模拟不同类型的项目呢?

这让我想到其他控件如何将DataTemplates添加到具有不同DataType的Resources集合中,并且控件知道搜索资源并选择正确的模板。不幸的是,我还没有弄清楚如何实现这一点。谁知道我怎么能做到这一点?它必须是可能的,因为微软在它们的控件中做到了。

2 个答案:

答案 0 :(得分:0)

我不太了解您的具体实现,以便为您提供准确的答案,但我可能会考虑使用您应用自定义模板的包装器控件,然后在其中放置一个ContentControl来呈现孩子们用他们自己模仿的东西来观察。

老实说虽然我不会使用网格来做这样的事情,但我过去做过的方式是使用数据绑定。为要显示的所有项目创建视图模型,并为其指定X和Y属性。然后在你的XAML中使用一个以Canvas作为背景的ItemsControl将它们全部绘制出来,并将项目的Canvas.Top和Canvas.Left dp绑定到X和Y&#39; s。这样,您的视图模型代码可以完全自由地将子项准确定位到您想要的位置,您也可以进行单元测试,而无需自己调用视图类。一旦我停止尝试使用XAML过于聪明,并且只是坚持使用它进行松散耦合的数据绑定,复杂的GUI设计突然变得非常容易实现。

答案 1 :(得分:0)

天啊,我不敢相信这么简单。实际上,我必须对@ ed-plunkett给予一些赞赏,因为他的所有显而易见的评论。我看起来有点困难,偶然发现如果我改变了这个:

<DataTemplate DataType="local:TestItem">

到此:

<DataTemplate DataType="{x:Type local:TestItem}">

它有效!

几分钟后,我发现了这篇文章:
http://briannoyesblog.azurewebsites.net/2013/11/23/use-xtype-with-wpf-implicit-datatemplates

*叹气*我希望我早些时候找到了。

因此,只要我使用{x:Type}语法,我就可以将DataTemplate放在范围内的任何位置并将其应用。