如何从继承的DataTemplate向基础Grid添加新元素?

时间:2012-06-08 14:00:48

标签: wpf xaml inheritance listbox datatemplate

我有两个对象:BicycleBicycleFullSuspension,它们继承了Bicycle并包含其他属性(字符串和小数)。我设法使DataTemplateSelector能够选择我的LbxItemTemplateBicycle DataTemplate或我的LbxItemTemplateFullSuspension DataTemplate,具体取决于ObservableCollection中对象所属的类。这两个模板都绑定到父模板ListBoxItemTemplate

我正在尝试显示有关ListBox中每个对象的信息,并且每个继承模板都应该向父DataTemplate中的网格添加更多字段。我的问题是我无法弄清楚如何从ListBoxItemTemplate中的一个继承模板向网格添加WPF元素。我无法在模板中为网格分配键,因此我不确定如何指定其他TextBlocks应该在父模板中的同一网格中结束。 (现在,其他TextBlocks堆叠在父网格的顶部。)

<DataTemplate x:Key="ListBoxItemTemplate">
        <Border Name="LbxItemTemplate" BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5">
        <Grid>
            <Grid.RowDefinitions>
                ...
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                ...
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Row="1" Grid.Column="0" Text="Bike Year:" />
            <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BikeYear}" />
            <TextBlock Grid.Row="2" Grid.Column="0" Text="Bike Color: "/>
            <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding BikeColor}"/>
            ...
            </Grid>
        </Border>
    </DataTemplate>
   <DataTemplate x:Key="LbxItemTemplateFullSuspension" DataType="{x:Type app:BicycleFullSuspension}">
        <Grid>
        <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
            <TextBlock Grid.Row="6" Grid.Column="0" Text="Shock Travel"/>
            <TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding ShockTravel}"/>
        </Grid>
    </DataTemplate>

我发现这些链接有助于达到这一点:

http://dariosantarelli.wordpress.com/2011/07/28/wpf-inheritance-and-datatemplates/ http://zamjad.wordpress.com/2009/12/31/applying-data-template-conditionally/

Is there a way to use data-template inheritance in WPF?

编辑:

我不确定为什么我不想将Border放在继承基础的模板上,而是通过在继承模板中将BorderPanel嵌套在Border内部(StackPanel包含带有基本模板内容的ContentPresenter)具有附加信息的网格),一切都排得很好:

工作解决方案,使用 XAMeLi

的输入
<DataTemplate x:Key="ListBoxItemTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                ...
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150" SharedSizeGroup="LabelColumnGroup" />
                <ColumnDefinition Width="150" SharedSizeGroup="LabelColumnGroup" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Row="1" Grid.Column="0" Text="Bike Year:" />
            <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BikeYear}" />
            ...
        </Grid>
   </DataTemplate>
   <DataTemplate x:Key="LbxItemTemplateFullSuspension" DataType="{x:Type app:BicycleFullSuspension}" >
        <Border BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5" Grid.IsSharedSizeScope="True" Width="500">
            <StackPanel>
            <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    ...
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelColumnGroup" />
                    <ColumnDefinition Width="Auto" SharedSizeGroup="LabelColumnGroup" />
                </Grid.ColumnDefinitions>
                ...
                <TextBlock Grid.Row="7" Grid.Column="0" Text="Shock Type: "/>
                <TextBlock Grid.Row="7" Grid.Column="1" Text="{Binding ShockType}"/>
                ...
            </Grid>
            </StackPanel>
        </Border>
    </DataTemplate>

1 个答案:

答案 0 :(得分:1)

您无法将UIElemets添加到数据模板,但您可以将较大的模板布局为看起来已将文本添加到基本模板。

基本上,你是在正确的道路上,只有大模板的布局是腐败的。 (太糟糕了,你省略了行和列的结构)

试试这个:

<DataTemplate x:Key="ListBoxItemTemplate">
    <Border Name="LbxItemTemplate" BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5">
    <Grid>
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"
                              SharedSizeGroup="LabelGroupColumn"/>
            ...
        </Grid.ColumnDefinitions>
      ....
    </Border>
</DataTemplate>

<DataTemplate x:Key="LbxItemTemplateFullSuspension">
    <Grid Grid.IsSharedSizeScope="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/><!--This will hold the default template-->
            <!--From here define the same structure as in the default template, if you have rows for margins and such-->
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"
                              SharedSizeGroup="LabelGroupColumn"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
        <TextBlock Grid.Row="1" Grid.Column="0" Text="Shock Travel"/>
        <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding ShockTravel}"/>
    </Grid>
</DataTemplate>

您的网格似乎具有Label-Value结构,并且您希望所有值都从相同的垂直线开始(从UX的角度来看,这非常好)。请注意列定义上的SharedSizeGroup setter和共同父项上的Grid.IsSharedSizeScope="True"。这将使标签列的宽度在网格之间保持同步。