如何重用WPF DataGridTemplateColumn(包括绑定)

时间:2012-08-07 15:43:06

标签: wpf resources datagridtemplatecolumn

在WPF数据网格中,我有一个定义为DataGridTemplateColumn的列,我需要在各种列上使用它。作为一个非常简单的示例,请将以下内容视为虚拟样本:

<DataGrid ItemsSource="{Binding Path=ItemList, Mode=OneWay}" AutoGenerateColumns="False" >                
    <DataGrid.Columns>

        <DataGridTemplateColumn Header="Name" MinWidth="130" Width="Auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <DockPanel LastChildFill="True">
                        <Image Source="component/Images/test.png"/>
                        <TextBlock Text="{Binding Path=Name, Mode=TwoWay, ValidatesOnDataErrors=True}"/>
                    </DockPanel>                                
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <DockPanel LastChildFill="True">
                        <Image Source="component/Images/test.png"/>
                        <TextBox Text="{Binding Path=Name, Mode=TwoWay, ValidatesOnDataErrors=True}"/>
                    </DockPanel>
                </DataTemplate>                            
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>

        <DataGridTextColumn Header="Company" Binding="{Binding Company, ValidatesOnDataErrors=True}" MinWidth="115" Width="Auto"/>                    
    </DataGrid.Columns>
</DataGrid>

举一个简单的例子,我怎样才能将Header = Name用于列的相同模板应用于Header = Company的列,而不必为每列重现整个模板?

我找到了this previous SO question的答案,他们使用以下资源来解释:

<Application.Resources> 
     <DataTemplate x:Key="CellTemplate"> 
     ... 
     </DataTemplate> 
     <DataTemplate x:Key="CellEdintingTemplate"> 
     ... 
     </DataTemplate> 
</Application.Resources> 

<DataGrid Style="{StaticResource MainGridStyle}"> 
    <DataGrid.Columns> 
        <DataGridTemplateColumn CellTemplate="{StaticResource MyFirstColumnCellTemplate}" CellEdintingTemplate="{StaticResource MyFirstColumnCellEdintingTemplate}"/> 
        ... 
    </DataGrid.Columns> 
<DataGrid>  

这让我95%,但我遗失的最后一块是如何处理数据绑定?如何在模板中创建某种类型的占位符,然后在网格中进行实际绑定?

修改 我一直在寻找并发现问题Create Common DataGridTemplateColumn这听起来像我想要做的事实上目前可能是不可能的。因此,如果其他任何人试图这样做,并看到这个问题我不能保证这是不可能的,但从这个链接似乎可能是。因此,只需复制每列的所有tempalte代码。

2 个答案:

答案 0 :(得分:8)

您可以将CellStyle属性设置为覆盖Template的{​​{1}}的样式。

DataGridCell中,使用Template绑定到ContentPresenter的{​​{1}},因为TemplatedParent.ContentTemplatedParent DataGridCell }

例如,

<Style x:Key="MyCellStyle" TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <Image Source="component/Images/test.png"/>
                    <ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" />
                </DockPanel>  
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<DataGrid ItemsSource="{Binding ItemList}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" CellStyle="{StaticResource MyCellStyle}" MinWidth="130" Width="Auto" />
        <DataGridTextColumn Header="Company" Binding="{Binding Company}" CellStyle="{StaticResource MyCellStyle}" MinWidth="115" Width="Auto"/>                    
    </DataGrid.Columns>
</DataGrid>

答案 1 :(得分:1)

链接Create Common DataGridTemplateColumn中有一个解决方案。

Poptart911创建了一个DatagridBoundTemplateColumn,可用于替换DataGridTemplateColumn,允许您在列上设置“Binding”属性。因此,您可以重用DataTemplate并将不同的DataContext分配给不同列的模板。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace OwensWpfFunStuff
{
public class DataGridBoundTemplateColumn : DataGridBoundColumn
{
    public DataTemplate CellTemplate { get; set; }
    public DataTemplate CellEditingTemplate { get; set; }

    protected override System.Windows.FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        return Generate(dataItem, CellEditingTemplate);
    }

    private FrameworkElement Generate(object dataItem, DataTemplate template)
    {
        var contentControl = new ContentControl { ContentTemplate = template, Content = dataItem };
        BindingOperations.SetBinding(contentControl, ContentControl.ContentProperty, Binding);
        return contentControl;
    }

    protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        return Generate(dataItem, CellTemplate);
    }
}
}