advapi advapi - 28 days ago 6
C# Question

Programmatically set a Binding to a DataTemplate

I'm writing a mockup to refactor and existing application and I've some issue setting a WPF Binding in code behind... the context is I've a RadPane (from Telerik suite, RadDocking control) and I want to set an header template. Right now I'm using this approach but when I dock-out a pane I got the header as System. instead of the content I got "System.Windows.Controls.StackPanel"

enter image description here

Here's my existing code

var pane = new RadDocumentPane();
var view = CreateViewContent(viewModel);

pane.DataContext = ((IView)view).DataContext;

pane.Content = view;

var dataTemplate = (DataTemplate)Application.Current.Resources["Default"];

var x = (StackPanel) dataTemplate.LoadContent();

x.DataContext = ((IView)view).DataContext;

pane.Header=x;
pane.Title=x;


I tought of something as

Binding binding = new Binding("?????");

BindingOperations.SetBinding(pane, HeaderedContentControl.HeaderTemplateProperty, binding);


but I don't know how to tell the binding that I want to refer to the
dataTemplate


UPDATE 1



The reason I have to create a DataTemplate is that I've to add some context menu functionality as defined here

<DataTemplate x:Key="Default">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Title,Mode=OneWay, UpdateSourceTrigger=Default}" Margin="3,0,0,0" >
<telerik:RadContextMenu.ContextMenu>
<telerik:RadContextMenu x:Name="ContextMenu">
<telerik:RadMenuItem Header="Chiudi questo">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<catel:EventToCommand Command="{Binding CloseCommand, Source={StaticResource PaneCommands}}" CommandParameter="{Binding}" DisableAssociatedObjectOnCannotExecute="False" />
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadMenuItem>
<telerik:RadMenuItem Header="Chiudi tutti">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<catel:EventToCommand Command="{Binding CloseAllCommand, Source={StaticResource PaneCommands}}" CommandParameter="{Binding}" DisableAssociatedObjectOnCannotExecute="False" />
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadMenuItem>
<telerik:RadMenuItem Header="Chiudi tutti tranne questo">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<catel:EventToCommand Command="{Binding CloseAllExceptThisCommand, Source={StaticResource PaneCommands}}" CommandParameter="{Binding}" DisableAssociatedObjectOnCannotExecute="False" />
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadMenuItem>
</telerik:RadContextMenu>
</telerik:RadContextMenu.ContextMenu>

<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<catel:EventToCommand Command="{Binding MouseDownCommand, Source={StaticResource PaneCommands}}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>


</StackPanel>
</DataTemplate>

Answer Source

The header template tells the control how you want to display the object you gave it for Header. If Header is just a string and you just want it displayed as ordinary UI text, you don't need to bother with a template. Likewise if Header is a control. But if you went to the trouble of writing a header DataTemplate, I imagine you had a reason for doing that.

So just give it the template:

pane.HeaderTemplate = dataTemplate;

Now, I have no idea what your template is doing or why you wrote one, or what's in the view's DataContext (should be a viewmodel, but in practice it could be literally anything).

But my guess is its something that you want to use as the DataContext of your header template, and that's exactly what it should be. If that's the case, you want to set the actual header content like this:

pane.Header = ((IView)view).DataContext;

...that is, unless ((IView)view).DataContext is likely to change at runtime. That can happen, and that's what bindings are for. Then you'd do this.

pane.SetBinding(
    HeaderedContentControl.HeaderProperty,
    new Binding("DataContext") { Source = view });

Looking at the documentation for RadDocumentPane, it has TopTemplate and TitleTemplate properties, and they don't mention HeaderTemplate. Lot going on there. But it seems to work like this.