在WPF中,在一个数据模板中使用另一个数据模板

6

我有两个数据模板,其中一个是另一个的子集,就像下面这样:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:igEditors="http://infragistics.com/Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Client.UI.WPF;assembly=Client.UI.WPF"
xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
>
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/Client.Resources.WPF.Styles;Component/Styles/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="XYZDataTemplate">
    <Grid x:Name="_rootGrid" DataContext="{Binding DataContext}" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
                    <controls:ValueDisplay Grid.Row="0" Grid.Column="0" LabelText="Build number" x:Name="buildNumber" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" 
                                   Margin="5,10,0,0">
            <igEditors:XamTextEditor  />
        </controls:ValueDisplay>
        <controls:ValueDisplay  Grid.Row="0" Grid.Column="1" LabelText="Tool version" x:Name="toolVersion" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" 
                                    Margin="20,10,0,0">
            <igEditors:XamTextEditor IsReadOnly="True"/>
        </controls:ValueDisplay>
               </Grid>

</DataTemplate>

and the other is like below:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:igEditors="http://infragistics.com/Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:BHI.ULSS.Client.UI.WPF;assembly=ULSS.Client.UI.WPF"
xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
>


<DataTemplate x:Key="ABCDataTemplate" >
    <Grid x:Name="_rootGrid" DataContext="{Binding DataContext}" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <controls:ValueDisplay Grid.Row="0" Grid.Column="0" LabelText="Build number" x:Name="buildNumber" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" 
                                   Margin="5,10,0,0">
            <igEditors:XamTextEditor  />
        </controls:ValueDisplay>
        <controls:ValueDisplay  Grid.Row="0" Grid.Column="1" LabelText="Tool version" x:Name="toolVersion" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" 
                                    Margin="20,10,0,0">
            <igEditors:XamTextEditor IsReadOnly="True"/>
        </controls:ValueDisplay>
        <controls:ValueDisplay Grid.Row="0" Grid.Column="2" LabelText="Size" ShowUnit="True" x:Name="size" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" 
                                   Margin="20,10,0,0">
            <igEditors:XamTextEditor/>
        </controls:ValueDisplay>
               </Grid>

</DataTemplate>

XYZDataTemplate是ABCDataTemplate的子集,因为两个数据模板中的前两个字段是相同的,所以我想知道是否可以用XYZDataTemplate的代码替换ABCDataTemplate中的冗余代码,以便更好地维护代码?请问有人能建议这是否是正确的方法,如果是,如何实现?

提前感谢, Sowmya

2个回答

9

如果您在XAML中有一些样板代码,可以使用ContentPresenter作为一种“宏”来在多个位置展开您的样板代码。首先,您需要定义一个DataTemplate,然后使用资源键与ContentPresenter来“展开”宏。以下是一个示例:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="boilerplate">
            <StackPanel Orientation="Horizontal">
                <Rectangle Width="100" Height="100" Stroke="Black" Fill="{Binding}"/>
                <Rectangle Width="100" Height="100" Stroke="Black" Fill="{Binding}"/>
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <StackPanel>
        <ContentPresenter ContentTemplate="{StaticResource boilerplate}" Content="Red"/>
        <ContentPresenter ContentTemplate="{StaticResource boilerplate}" Content="Blue"/>
    </StackPanel>
</Grid>

作为一个真正的模板,你可以使用数据绑定。把它想象成只有一个项目的ItemsControl。如果没有绑定,可以省略Content属性。你可以把它看作是“参数”宏。
过度使用这个功能会使你的XAML更难读,并且会有一定的性能损失,因此请谨慎使用。最后,有一些限制,即“宏”始终扩展为一个顶级元素,因此您不能使用单个ContentPresenter将两个元素添加到单个Panel中。

谢谢Rick的建议,这帮助我理解如何重用数据模板 :)! - Sowmya
我该如何动态选择ContentPresenter的ContentTemplate? - RDV
1
@RDV - 我通过拥有自己的IValueConverter来解决了这个问题。转换器可以具有在xaml中可访问的属性。当您定义转换器(分配x:key)时,可以将键控模板分配给转换器属性。然后,在ContentPresenter中绑定您的内容模板到数据,并传递将返回您的模板之一的转换器。 如果您需要静态选择器(运行时中的一个),则有一个ITemplateSelector(或类似名称)。 - Masius

1
使用VS2010,我会考虑使用一个UserControlUserControl会自动从其父级继承DataContext属性,具有设计时支持,并且您不必硬编码资源路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接