如何在另一个DataTemplate中继承DataTemplate

时间:2012-06-27 22:32:17

标签: wpf datatemplate

好的,所以我不知道这是否可行但是?我正在尝试填充DataGrid(确切地说是Telerik RadGridView)并且想要动态确定编辑控件。我正在尝试创建一个网格来显示正在导入到应用程序中的数据并显示三列(属性名称,入站数据和当前数据库数据)。根据我的对象类中的属性,“属性名称”列需要在其前面放置一个CheckBox。接下来是其他列,只要有条件地附加按钮,就可以进行查找(TextBox或TextBlock将位于按钮前面以显示当前值)。我希望这能解释我正在尝试做什么。下面是我提出的XAML。

哦进入WPF MVVM C#应用程序。

感谢您提供的任何帮助。

<UserControl x:Class="PulseHL7Importer.Views.DetailView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
         xmlns:p="clr-namespace:PulseHL7Importer.Properties"
         xmlns:fw="clr-namespace:PulseHL7Importer.Framework"
         xmlns:vm="clr-namespace:PulseHL7Importer.ViewModels"
         mc:Ignorable="d" 
         d:DesignHeight="200" d:DesignWidth="961">
<UserControl.Resources>
    <telerik:BooleanToVisibilityConverter x:Key="BooleanVisibilityConverter" />
    <DataTemplate x:Key="AddCheckBox">
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding HasCheckBox}" Value="True" />
        </DataTemplate.Triggers>
        <CheckBox IsChecked="{Binding IsChecked}" Margin="2,0,5,0" VerticalAlignment="Center" HorizontalAlignment="Center" />
    </DataTemplate>
    <DataTemplate x:Key="AddTextBlock">
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding IsReadOnly}" Value="True" />
        </DataTemplate.Triggers>
        <TextBlock Text="{Binding Value}" />
    </DataTemplate>
    <DataTemplate x:Key="AddTextBox">
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding IsReadOnly}" Value="False" />
        </DataTemplate.Triggers>
        <TextBox Text="{Binding Value}" />
    </DataTemplate>
    <DataTemplate x:Key="AddButton">
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding HasLookup}" Value="True" />
        </DataTemplate.Triggers>
        <Button Content="..." Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"
                VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </DataTemplate>
    <DataTemplate x:Key="ConditionalTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <ContentPresenter Grid.Column="0" Content="{Binding}" ContentTemplate="{StaticResource AddCheckBox}" />
            <ContentPresenter Grid.Column="1" Content="{Binding}" ContentTemplate="{StaticResource AddTextBlock}" />
            <ContentPresenter Grid.Column="1" Content="{Binding}" ContentTemplate="{StaticResource AddTextBox}" />
            <ContentPresenter Grid.Column="2" Content="{Binding}" ContentTemplate="{StaticResource AddButton}" />
        </Grid>
    </DataTemplate>
</UserControl.Resources>
<Grid d:DataContext="{d:DesignInstance vm:DetailViewModel}">
    <telerik:RadDockPanel Width="Auto">
        <!-- Toolbar -->
        <telerik:RadDockPanel telerik:RadDockPanel.Dock="Top">
            <telerik:RadToolBar OverflowButtonVisibility="Collapsed" />
        </telerik:RadDockPanel>

        <!-- Warnings and Errors -->
        <telerik:RadDockPanel telerik:RadDockPanel.Dock="Bottom">
            <telerik:GroupBox Header="Warnings and Errors"
                              telerik:Theming.Theme="{Binding Source={x:Static p:Settings.Default}, Path=SelectedTheme}">
                <TextBox Height="60" IsReadOnly="True"
                         VerticalScrollBarVisibility="Auto"
                         Background="FloralWhite" />
            </telerik:GroupBox>
        </telerik:RadDockPanel>

        <!-- Grid Area -->
        <telerik:RadDockPanel Width="Auto">
            <telerik:RadGridView Name="DetailGridView" Width="Auto" AutoGenerateColumns="False" RowIndicatorVisibility="Collapsed"
                                 CanUserDeleteRows="False" CanUserInsertRows="False" CanUserReorderColumns="False" 
                                 CanUserSortColumns="False" IsFilteringAllowed="False" ColumnWidth="*"
                                 ShowGroupPanel="False" ItemsSource="{Binding Path=Properties}" >
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="Name" DataMemberBinding="{Binding Path=Value}">
                        <telerik:GridViewDataColumn.CellTemplate>
                            <DataTemplate>
                                <ContentPresenter ContentTemplate="{StaticResource ConditionalTemplate}" Content="{Binding Path=Properties}" />
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellTemplate>
                        <telerik:GridViewDataColumn.CellEditTemplate>
                            <DataTemplate>
                                <ContentPresenter ContentTemplate="{StaticResource ConditionalTemplate}" Content="{Binding Path=Properties}" />
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellEditTemplate>
                    </telerik:GridViewDataColumn>
                    <telerik:GridViewDataColumn Header="Client Data" DataMemberBinding="{Binding Path=ClientData.Value}">
                        <telerik:GridViewDataColumn.CellEditTemplate>
                            <DataTemplate>
                                <ContentPresenter ContentTemplate="{StaticResource ConditionalTemplate}" Content="{Binding Path=ClientData}" />
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellEditTemplate>
                    </telerik:GridViewDataColumn>
                    <telerik:GridViewDataColumn Header="Pulse Data" DataMemberBinding="{Binding Path=PulseData.Value}">
                        <telerik:GridViewDataColumn.CellEditTemplate>
                            <DataTemplate>
                                <ContentPresenter ContentTemplate="{StaticResource ConditionalTemplate}" Content="{Binding Path=PulseData}" />
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellEditTemplate>
                    </telerik:GridViewDataColumn>
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>
        </telerik:RadDockPanel>
    </telerik:RadDockPanel>
</Grid>

3 个答案:

答案 0 :(得分:0)

通常ContentPresenters获取相应的隐式模板,因此您只需要将Content绑定到您想要模板化的属性或DataContext,并且应该模板化。

(不确定这是否适用于你的问题,因为我不太明白你想说什么)

答案 1 :(得分:0)

您可以将DataTemplate的DataType属性设置为不同视图模型使用的不同类。

如果同一个viewmodel类必须根据内部值有条件地返回不同的模板,则可以在App.xaml中声明模板

<DataTemplate x:Key="AddCheckBox">
     ...
</DataTemplate>

然后使用

在viewmodel中引用它
public DataTemplate ConditionalTemplate
    {
        get
        {
            if (this.ConditionMet)
                return Application.Current.Resources["AddCheckBox"] as DataTemplate;
            else
                return Application.Current.Resources["DifferentTemplate"] as DataTemplate;
        }
    }

希望这有帮助

答案 2 :(得分:0)

好的,我已经设法通过一些黑客来解决这个问题。我现在正在CellEditTemplateSelector中动态创建DataTemplate。这允许我检查所有属性并添加适当单元格的控件和绑定。

这是基本的XAML网格:

                <telerik:RadGridView Name="DetailGridView" Width="Auto" AutoGenerateColumns="False" RowIndicatorVisibility="Collapsed"
                                 CanUserDeleteRows="False" CanUserInsertRows="False" CanUserReorderColumns="False" 
                                 CanUserSortColumns="False" IsFilteringAllowed="False" ColumnWidth="*"
                                 ShowGroupPanel="False" ItemsSource="{Binding Path=Properties}">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn Header="Name" IsReadOnlyBinding="{Binding Path=IsReadOnly}"
                                                DataMemberBinding="{Binding Path=Value}"
                                                CellTemplateSelector="{StaticResource CellTemplateSelector}"
                                                CellEditTemplateSelector="{StaticResource CellEditTemplateSelector}">
                        <telerik:GridViewDataColumn.CellStyle>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="True">
                                        <Setter Property="Canvas.Background" Value="LightGoldenrodYellow" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=IsGroupItem}" Value="True">
                                        <Setter Property="Canvas.Background"  Value="LightGray" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=IsRequired}" Value="True">
                                        <Setter Property="TextElement.Foreground" Value="Red" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </telerik:GridViewDataColumn.CellStyle>
                    </telerik:GridViewDataColumn>
                    <telerik:GridViewMaskedTextBoxColumn Header="Client Data"
                                                DataMemberBinding="{Binding Path=ClientData.Value}"
                                                CellEditTemplateSelector="{StaticResource CellEditTemplateSelector}">
                        <telerik:GridViewMaskedTextBoxColumn.CellStyle>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=ClientData.IsReadOnly}" Value="True">
                                        <Setter Property="Canvas.Background" Value="LightGoldenrodYellow" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=IsGroupItem}" Value="True">
                                        <Setter Property="Canvas.Background"  Value="LightGray" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </telerik:GridViewMaskedTextBoxColumn.CellStyle>
                    </telerik:GridViewMaskedTextBoxColumn>
                    <telerik:GridViewDataColumn Header="Pulse Data"
                                                DataMemberBinding="{Binding Path=PulseData.Value}" 
                                                CellEditTemplateSelector="{StaticResource CellEditTemplateSelector}">
                        <telerik:GridViewDataColumn.CellStyle>
                            <Style>
                                <Style.Triggers>
                                   <DataTrigger Binding="{Binding Path=PulseData.IsReadOnly}" Value="True">
                                        <Setter Property="Canvas.Background" Value="LightGoldenrodYellow" />
                                   </DataTrigger>
                                   <DataTrigger Binding="{Binding Path=IsGroupItem}" Value="True">
                                        <Setter Property="Canvas.Background"  Value="LightGray" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </telerik:GridViewDataColumn.CellStyle>
                    </telerik:GridViewDataColumn>
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>

这是CellEditTemplateSelector:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using Telerik.Windows.Controls.GridView;
using System.Windows.Markup;
using System.Windows.Media;

namespace PulseHL7Importer.Framework
{
public class CellEditTemplateSelector : DataTemplateSelector
{
    public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
    {
        FrameworkElement element = (FrameworkElement)container;

        if (element != null && item != null && item is Property)
        {
            GridViewCell cell = (GridViewCell)container;
            Property property = (Property)item;
            Column column = null;
            StringBuilder grid = new StringBuilder();
            BrushConverter converter = new BrushConverter();

            #region Control Header

            grid.Append("<DataTemplate");
            grid.Append(" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"");
            grid.Append(" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"");
            grid.Append(" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"");
            grid.Append(" xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"");
            grid.Append(" xmlns:telerik=\"http://schemas.telerik.com/2008/xaml/presentation\"");
            grid.Append(" mc:Ignorable=\"d\"");
            grid.Append(">");

            #endregion  //Control Header

            switch (cell.Column.Header.ToString().Replace(" ", "").ToUpper())
            {
                case "NAME":
                    grid.Append("<StackPanel Orientation=\"Horizontal\"");
                    if (property.IsGroupItem)
                        grid.Append(" Background=\"LightGray\">");
                    else
                        grid.Append(">");
                    if (property.HasCheckBox)
                    {
                        grid.Append("<Grid Width=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                            " Path=ActualWidth}\">");
                        grid.Append("<Grid.ColumnDefinitions>");
                        grid.Append("<ColumnDefinition Width=\"Auto\" />");
                        grid.Append("<ColumnDefinition Width=\"*\" />");
                        grid.Append("</Grid.ColumnDefinitions>");
                    }
                    if (property.HasCheckBox)
                        grid.Append("<CheckBox Grid.Column=\"0\" IsChecked=\"{Binding Path=IsChecked}\" Margin=\"3,2,3,0\" />");
                    if (property.IsReadOnly)
                        grid.AppendFormat("<TextBlock{0} Text=\"{{Binding Path=Value}}\"", property.HasCheckBox ? " Grid.Column=\"1\"" : "");
                    else
                        grid.AppendFormat("<TextBox{0} Text=\"{{Binding Path=Value}}\"", property.HasCheckBox ? " Grid.Column=\"1\"" : "");
                    if (!property.HasCheckBox)
                    {
                        grid.Append(" Margin=\"15,0,0,0\" ");
                        grid.Append(" Width=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                            " Path=ActualWidth}\"");
                    }
                    if(!property.IsReadOnly)
                        grid.Append(" BorderBrush=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                            " Path=BorderBrush}\"");
                    grid.Append(" Background=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                        " Path=Background}\" />");
                    if (property.HasCheckBox)
                        grid.Append("</Grid>");
                    grid.Append("</StackPanel>");
                    break;
                case "CLIENTDATA":
                    column = property.ClientData;

                    grid.Append(this.BuildColumn(property, "ClientData", column));
                    break;
                case "PULSEDATA":
                    column = property.PulseData;

                    grid.Append(this.BuildColumn(property, "PulseData", column));
                    break;
            }

            #region Control Footer

            grid.Append("</DataTemplate>");

            #endregion

            if (!string.IsNullOrWhiteSpace(grid.ToString()))
            {
                return (DataTemplate)XamlReader.Parse(grid.ToString());
            }
        }

        return base.SelectTemplate(item, container);
    }

    string BuildColumn(Property property, string columnName, Column column)
    {
        StringBuilder grid = new StringBuilder();

        try
        {
            grid.Append("<StackPanel Orientation=\"Horizontal\"");
            if (property.IsGroupItem)
                grid.Append(" Background=\"LightGray\">");
            else if (column.IsReadOnly)
                grid.Append(" Background=\"LightGoldenrodYellow\">");
            else
                grid.Append(">");
            if (column.Options != null && column.Options.Count > 0)
            {
                grid.Append("<telerik:RadComboBox SelectedValue=\"{Binding Path=ClientData.Value}\"" +
                    " ItemsSource=\"{Binding Path=" + columnName + ".Options}\"" +
                    " IsReadOnly=\"{Binding Path=" + columnName + ".IsReadOnly}\"" +
                    " Width=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                    " Path=ActualWidth}\" />");
            }
            else
            {
                grid.Append("<Grid Width=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                    " Path=ActualWidth}\">");
                grid.Append("<Grid.ColumnDefinitions>");
                if (column.HasCheckBox)
                    grid.Append("<ColumnDefinition width=\"Auto\" />");
                grid.Append("<ColumnDefinition Width=\"*\" />");
                if (column.HasButton)
                    grid.Append("<ColumnDefinition Width=\"21\" />");
                grid.Append("</Grid.ColumnDefinitions>");
                if (column.HasCheckBox)
                    grid.Append("<CheckBox Grid.Column=\"0\"" +
                        " IsChecked=\"{Binding Path=" + columnName + ".IsChecked}\" Margin=\"3,2,3,0\" />");
                if (column.IsReadOnly)
                {
                    grid.AppendFormat("<TextBlock{0} Text=\"{{Binding Path=" + columnName + ".Value}}\"",
                        column.HasCheckBox ? " Grid.Column=\"1\"" : " Grid.Column=\"0\"");
                    if (property.IsGroupItem)
                        grid.Append(" Margin=\"4,3,3,0\"");
                    else
                        grid.Append(" Margin=\"4,0,0,0\"");
                }
                else if (!string.IsNullOrWhiteSpace(column.Mask))
                {
                    grid.AppendFormat("<telerik:RadMaskedTextBox{0} Value=\"{{Binding Path=" + columnName + ".Value}}\"" +
                        " Mask=\"{{Binding Path=" + columnName + ".Mask}}\"",
                        column.HasCheckBox ? " Grid.Column=\"1\"" : " Grid.Column=\"0\"");
                }
                else
                    grid.AppendFormat("<TextBox{0} Text=\"{{Binding Path=" + columnName + ".Value}}\"",
                        column.HasCheckBox ? " Grid.Column=\"1\"" : " Grid.Column=\"0\"");
                if (!property.IsReadOnly)
                    grid.Append(" BorderBrush=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                        " Path=BorderBrush}\"");
                grid.Append(" Background=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel, AncestorLevel=1}," +
                    " Path=Background}\" />");
                if (column.HasButton)
                    grid.AppendFormat("<Button Grid.Column=\"{0}\" Content=\"...\" />",
                        column.HasCheckBox ? "2" : "1");
                grid.Append("</Grid>");
            }
            grid.Append("</StackPanel>");

            return grid.ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            grid.Clear();
        }

        return string.Empty;
    }
}
}