FaisalM
FaisalM

Reputation: 756

Use ControlTemplate from resource in a DataGridColumn

I created a datagrid that is populated from a list. The list implementation is like this.

ObservableCollection<CFImportResult> CFImportResults
public class CFImportResult
{
    public string CFComponentName { get; set; }
    public string CFport { get; set; }
    public PortType CFPortType { get; set; }
    public string PlatformCompName { get; set; }
    public string PlatformCompPort { get; set; }
    public PortType PlatformCompType { get; set; }
    public string Result { get; set; }
}

Here two of the grid columns are special that they shows both an image and a text. XAML is given below.

<DataGrid ItemsSource="{Binding Path=CFImportResults}" Height="500" AutoGenerateColumns="False" CanUserAddRows="False" VerticalAlignment="Top" Background="Transparent" VerticalScrollBarVisibility="Auto" BorderBrush="Gray">
    <DataGrid.Columns>
        <DataGridTextColumn Header="CF Component" Binding="{Binding Path=CFComponentName}" Width="140"/>
        <DataGridTemplateColumn Header="CF port" Width="140">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Height="16" Width="16" Source="{Binding CFPortIcon}"/>
                        <TextBox Text="{Binding CFport}" BorderBrush="Transparent"/>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Platform Component" Binding="{Binding Path=PlatformCompName}" Width="140"/>
        <DataGridTemplateColumn Header="Platform port" Width="140">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Height="16" Width="16" Source="{Binding PlatformCompIcon}"/>
                        <TextBox Text="{Binding PlatformCompPort}" BorderBrush="Transparent"/>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Status" Binding="{Binding Path=Result}" Width="140"/>
    </DataGrid.Columns>
</DataGrid>

This is working fine. Now I want to move the DataTemplate part to the ResourceDictionary section. I tried to create a ControlTemplate with the TextBox and Image controls. But i don't know how to use it inside the DataGridTextColumn (It doesn't have any ItemSource field). Is this really possible?

<ResourceDictionary>
    <ControlTemplate x:Key="PortTemplate" TargetType="{x:Type DataGridCell}">
        <StackPanel Orientation="Horizontal">
            <Image Height="16" Width="16" Source="{Binding CFPortIcon}"/>
            <TextBox Text="{Binding CFport}" BorderBrush="Transparent"/>
        </StackPanel>
    </ControlTemplate>
</ResourceDictionary>

 <DataGridTextColumn Header="CF port" ????="{StaticResource PortTemplate}" Width="140"/>

Upvotes: 0

Views: 343

Answers (1)

mm8
mm8

Reputation: 169320

Move the DataTemplates to the ResourceDictionary and give them an x:Key:

<DataTemplate x:Key="a">
    <StackPanel Orientation="Horizontal">
        <Image Height="16" Width="16" Source="{Binding CFPortIcon}"/>
        <TextBox Text="{Binding CFport}" BorderBrush="Transparent"/>
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="b">
    <StackPanel Orientation="Horizontal">
        <Image Height="16" Width="16" Source="{Binding PlatformCompIcon}"/>
        <TextBox Text="{Binding PlatformCompPort}" BorderBrush="Transparent"/>
    </StackPanel>
</DataTemplate>

You can then set the CellStyle properties of the DataGridTemplateColumns using the StaticResource markup extension like this:

<DataGrid ItemsSource="{Binding Path=CFImportResults}" Height="500" AutoGenerateColumns="False" CanUserAddRows="False" VerticalAlignment="Top" Background="Transparent" VerticalScrollBarVisibility="Auto" BorderBrush="Gray">
    <DataGrid.Columns>
        <DataGridTextColumn Header="CF Component" Binding="{Binding Path=CFComponentName}" Width="140"/>
        <DataGridTemplateColumn Header="CF port" Width="140" CellStyle="{StaticResource a}" />
        <DataGridTextColumn Header="Platform Component" Binding="{Binding Path=PlatformCompName}" Width="140"/>
        <DataGridTemplateColumn Header="Platform port" Width="140" CellStyle="{StaticResource b}" />
        <DataGridTextColumn Header="Status" Binding="{Binding Path=Result}" Width="140"/>
    </DataGrid.Columns>
</DataGrid>

A DataGridTextColumn has no concept of a template though.

Also note that you still need to define two separate data templates because the binding paths in them differ.

Upvotes: 1

Related Questions