1

I have created a custom control which inherits from DataGrid and adds a header property in the same way that HeaderedContentControl has a header.

[Bindable(true)]
public Object Header
{
    get { return (Object)GetValue(HeaderProperty); }
    set { SetValue(HeaderProperty, value); }
}

// Using a DependencyProperty as the backing store for Header.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderProperty =
    DependencyProperty.Register("Header", typeof(Object), typeof(ExtendedDataGrid), new PropertyMetadata(null, HeaderProperty_Changed));

private static void HeaderProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ExtendedDataGrid ctrl = (ExtendedDataGrid)d;
    ctrl.OnHeaderChanged(e.OldValue, e.NewValue);
}

protected virtual void OnHeaderChanged(object oldValue, object newValue)
{
    RemoveLogicalChild(oldValue);
    AddLogicalChild(newValue);
}       

The control template binds a ContentPresenter content to the HeaderProperty. (This is inside the Scrollviewer ControlTemplate inside the DataGrid ControlTemplate so I can't use ContentSource)

<ContentPresenter Grid.Row="0" Grid.ColumnSpan="99"
                    Margin="0"
                    Content="{Binding Header, RelativeSource={RelativeSource AncestorType{x:Type extended:ExtendedDataGrid}}}"/>

The content is set correctly to the header property.

I have found that the content presenter does not inherit the DataGrid DataContext so I have to set the DataContext separately. This means that any bindings inside the header will not bind as expected, because the DataContext for all Elements in the header is null. I can see from the ContentPresenter implementation that it specifically sets the DataContext to null on Initialise so I understand why this is happening.

Question

However the part I do not understand and I am interested to know is how the ContentPresenter elements in many other controls correctly inherit the DataContext without (from what I can see) any different code/xaml? For example the Button ContentPresenter or the HeaderContentControl ContentPresenters.

daniele3004
  • 13,072
  • 12
  • 67
  • 75
ndonohoe
  • 9,320
  • 2
  • 18
  • 25
  • In control template you have to use `TemplateBinding`. – Sinatr Nov 14 '14 at 14:14
  • Please explain how that will help me. As I've stated the ContentPresenter is inside a ScrollViewer ControlTemplate so TemplateBinding would give me incorrect results. – ndonohoe Nov 14 '14 at 15:06
  • `Button`s `ContentPresenter` is using `TemplateBinding` (100% sure). I am trying to understand what you are possible asking (if it's not a binding problem) and just can't understand ;) `DataContext`? It can be set yes, it's inherited by `Button`, but it's not used in `Button` control template. So once again, what is your question? – Sinatr Nov 14 '14 at 15:26
  • The question is about the DataContext on ContentPresenter, if you look at the default Button Style http://msdn.microsoft.com/en-us/library/ms753328(v=vs.110).aspx the ContentPresenter does not have either DataContext or Content set. I know that the Content is found because the default ContentSource for a ContentPresenter is Content, but I do not know how the DataContext is correctly inherited from the parent (Button in this case), yet it is not on my example ContentPresenter. – ndonohoe Nov 14 '14 at 15:34
  • I found some articles addressing this topic: https://agsmith.wordpress.com/2008/07/14/who-set-the-datacontext/ and the answers to these questions: http://stackoverflow.com/q/12388402/138078 and http://stackoverflow.com/q/21767363/138078. – Gerard Nov 25 '14 at 08:58
  • Thanks for the links, however they just explain the difference between datacontext and content and how some controls approach setting them. I know that the ContentPresenter does not inherit the DataContext normally as I can see it in the source code, my question is why not all ContentPresenters seem to follow this rule, Button for example uses a ContentPresenter yet whatever you put in Button.Content correctly inherits the DataContext of the button, despite being in a ContentPresenter (which normally doesn't inherit DataContext). I hope the explanation is enough. – ndonohoe Nov 25 '14 at 13:57

1 Answers1

0

[Sort of an anwer, because I have no idea what question I am answering ;) ]

Here is ContentPresenter of Button control template (what you see here is just an example of some possible template)

    <ContentPresenter RecognizesAccessKey="True"
        Content="{TemplateBinding ContentControl.Content}"
        ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
        ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
        Margin="{TemplateBinding Control.Padding}"
        HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
        SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />

As you can see it uses TemplateBinding. There is no DataContext in template. You do not use DataContext, nor Binding in templates.

Bennik2000
  • 1,112
  • 11
  • 25
Sinatr
  • 20,892
  • 15
  • 90
  • 319