Dror
Dror

Reputation: 2588

Binding a DataGrid's CellTemplate content to an Element or a DependencyProperty defined on the templated CustomControl

I'm using WPF's regular DataGrid inside a custom control. One of the DataGrid's cell template content should be bound to a the Text of a Textblock or to a DependencyProperty on the custom control. (If I could bind it to any of them it's good enough for me)

I tried to do the following binding with the ElementName but it didn't work. I keep getting an DependencyProperty.UnsetValue -

<DataGridTemplateColumn Header="Test">
     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
             <ContentPresenter>
                <ContentPresenter.Content>
                    <MultiBinding Converter="{StaticResource TextToSpecialTextblockConverter}">
                       <Binding Path="SomeTextOnTheViewModel"/>
                       <Binding ElementName="SearchBox" Path="Text" Mode="OneWay"/>
                    </MultiBinding>
                </ContentPresenter.Content>
             </ContentPresenter>
         </DataTemplate>
     </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Binding to a DependencyProperty also doesn't work.

<DataGridTemplateColumn Header="Test">
     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
             <ContentPresenter>
                <ContentPresenter.Content>
                    <MultiBinding Converter="{StaticResource TextToSpecialTextblockConverter}">
                       <Binding Path="SomeTextOnTheViewModel"/>
                       <Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="SomeDP" />
                    </MultiBinding>
                </ContentPresenter.Content>
             </ContentPresenter>
         </DataTemplate>
     </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

I hope someone could help me out!

Thanks!

Upvotes: 1

Views: 22129

Answers (1)

Phil
Phil

Reputation: 42991

If the property Property is defined on a view model set on the DataContext of the control or DataGrid then this sample works:

Resources:

    <DataTemplate x:Key="template">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Test"/>
            <TextBlock Text="{Binding Path=DataContext.Property,RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
        </StackPanel>
    </DataTemplate>

DataGrid

<DataGrid ItemsSource="{Binding Items}" ...>
    <DataGrid.Columns>
        <DataGridTemplateColumn CellTemplate="{StaticResource template}" />

The DependencyProperty change notification could update the view model.

For example:

    public static readonly DependencyProperty TestProperty =
        DependencyProperty.Register("Test", typeof (string), typeof (DataGridComboBoxColumn), new PropertyMetadata(default(string), PropertyChangedCallback));

    public string Test
    {
        get { return (string) GetValue(TestProperty); }
        set { SetValue(TestProperty, value); }
    }

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        ((MyControl) dependencyObject).OnTestChanged();
    }

    private void OnTestChanged()
    {
        ((MyViewModel) theGrid.DataContext).Property = Test;
    }

In order to bind to a dependency property Test using a template binding use this

<DataTemplate x:Key="template2">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Test: "/>
        <TextBlock Text="{Binding Path=Test, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}}"/>
    </StackPanel>
</DataTemplate>

<Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <DataGrid ItemsSource="{TemplateBinding ItemsSource}" AutoGenerateColumns="True">
                        <DataGrid.Columns>
                            <DataGridTemplateColumn Header="Test" CellTemplate="{StaticResource template2}" />
                        </DataGrid.Columns>
                    </DataGrid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Where CustomControl1 is

public class CustomControl1 : ItemsControl
{
    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof (CustomControl1),
            new FrameworkPropertyMetadata(typeof (CustomControl1)));
    }

    public static readonly DependencyProperty TestProperty =
        DependencyProperty.Register("Test", typeof (string), typeof (CustomControl1), new PropertyMetadata(default(string)));

    public string Test
    {
        get { return (string) GetValue(TestProperty); }
        set { SetValue(TestProperty, value); }
    }
}

Upvotes: 6

Related Questions