2012-06-27 4 views
0

ОК, Так что я не знаю, возможно ли это, но? Я пытаюсь заполнить DataGrid (точнее, Telerik RadGridView) и хочу динамически определять элементы управления редактированием. Я пытаюсь создать сетку для отображения данных, которые импортируются в приложение, и отображать три столбца (имя свойства, входящие данные и текущие данные базы данных). Основываясь на свойстве в моем классе объектов, в столбце «Имя свойства» должен быть установлен флажок CheckBox. Это следует за другими столбцами до условного добавления кнопки, чтобы можно было выполнить поиск (TextBox или TextBlock были бы перед кнопкой, чтобы отобразить текущее значение). Надеюсь, это объясняет, что я пытаюсь сделать. Ниже приведен XAML.Как наследовать DataTemplate в другом DataTemplate

О, это входит в приложение 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> 

ответ

0

ОК, мне удалось решить эту проблему с помощью взлома. Теперь я динамически создаю DataTemplate в CellEditTemplateSelector. Это позволяет мне проверять все свойства и добавлять элементы управления и привязки для соответствующих ячеек.

Вот основные 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; 
    } 
} 
} 
0

Обычно ContentPresenters получить соответствующий неявный шаблон, так что вам просто нужно связать Content один к собственности или DataContext вы хотите шаблонные, и она должна быть шаблонными.

(Не уверен, если это относится к вашей проблеме, как я не совсем понимаю, что вы хотели сказать)

+0

Ну я думаю, что это имеет больше общего с отображением одного или нескольких элементов управления условно. В основном это работает с тем исключением, что отображаются все различные элементы управления (CheckBox, TextBox и Button). Поэтому я думаю, что реальный вопрос заключается в том, как я могу отображать только определенные элементы управления? – dhamilton

+0

@dhamilton: Ну, вы обычно различаете по типу и выбираете подходящий элемент управления/шаблона. Для этого можно использовать 'ContentTemplateSelector'. –

+0

Ну, я пытался немного переработать это и думаю, что у меня есть разумное решение под рукой. Я считаю, что это сводит меня к решению привязки между моей сеткой и шаблонами данных, которые выбираются. В основном у меня есть класс «Свойства», этот класс имеет некоторые свойства, которые управляют первым столбцом моей сетки. Он также имеет некоторые свойства (ClientData и PusleData), которые являются подклассами; которые используются в моих последних двух столбцах.Моя проблема заключается в том, что в селекторе шаблонов и сам шаблон привязывается к «Свойствам», а не к «ClientData» и «PulseData». Вот код. – dhamilton

0

Вы можете установить DataType свойство вашего DataTemplate для различных классов, используемых вашего различного ViewModels.

Если же класс 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; 
     } 
    } 

Надеюсь, что это поможет

Смежные вопросы