How to use WPF ContentControl 's content with DataTemplate

4k views Asked by At

I copied some resource about custom button using Content control. And I changed something to be <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=Content}"> For the dataTempalte

<DataTemplate x:Key="PriceDataTemplate" DataType="m:ClickTradeViewModel">
    <Button Command="{Binding ExecuteCommand}" Cursor="Hand">
        <Button.Style>
            <Style TargetType="Button">
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Border Background="{TemplateBinding Background}">
                                <ContentPresenter Content="{TemplateBinding Content}" />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="DarkGray" />
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="#FF345C8B" />
                    </Trigger>
                    <DataTrigger Binding="{Binding IsExecuting}" Value="True">
                        <Setter Property="Background" Value="DimGray" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>

        <UserControl>
            <UserControl.Template>
                <ControlTemplate TargetType="UserControl">
                    <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=Content}"></TextBlock>
                </ControlTemplate>
            </UserControl.Template>
        </UserControl>
    </Button>
</DataTemplate>

And for the actual Button, it used

<ContentControl x:Name="AskContentControl" Grid.Column="2" 
                Margin="5,0,0,0"
                Content="{Binding QQ.Bid}" 
                ContentTemplate="{StaticResource PriceDataTemplate}"/>

I expect the Content will use double Bid's tostring method to render the content, but it shows nothing inside (gray color). In the plot the left side shows the price did exists.

enter image description here

Update: I am not sure what's going on, but with some change <TextBlock Text="{Binding QQ.Ask}"></TextBlock> and set

<ContentControl x:Name="AskContentControl" Grid.Column="2" 
                Margin="5,0,0,0"
                Content="{Binding}"
                ContentTemplate="{StaticResource PriceDataTemplate}"/> makes it work. 

The problem is then I had to explicitly set the PriceDataTemplate several times for different properties.

2

There are 2 answers

1
King King On BEST ANSWER

It does not work because you are using a Binding with RelativeSource finding a ContentControl but UserControl is also a ContentControl, so what it found is actually the UserControl, not the root ContentControl you thought. In this case you can specify some AncestorLevel as 2 (to find the second ContentControl):

<TextBlock Text="{Binding 
           RelativeSource={RelativeSource Mode=FindAncestor,
                           AncestorType=ContentControl, AncestorLevel=2},
           Path=Content}"></TextBlock>

However it's not really safe and in this case the implicit DataContext is actually the Content you set for your ContentControl (this DataContext flows down from the DataTemplate through the UserControl's Template). So the Binding can be just simple like this:

<TextBlock Text="{Binding}"></TextBlock>

Note I supposed you keep setting the ContentControl's Content to {Binding QQ.Bid}.

0
Eric Ouellet On

This is a full working solution... I'm late but perhaps it could help others?

<UserControl
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ParametricStudyAnalysis.ScopeSelection.Special"
             xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid" x:Class="ParametricStudyAnalysis.ScopeSelection.Special.UserControlAddSpecialSignal"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.DataContext>
        <local:UserControlAddSpecialSignalModel></local:UserControlAddSpecialSignalModel>
    </UserControl.DataContext>

    <UserControl.Resources>
        <DataTemplate DataType="{x:Type local:UserControlSpecialSignalTtrModel}">
            <local:UserControlSpecialSignalTtr/>
        </DataTemplate>     
    </UserControl.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>


        <GroupBox Header="Signal type" Grid.Row="0" Padding="5">
            <xcdg:DataGridControl Name="DataGrid" SelectionMode="Single" ItemsSource="{Binding SpecialSignalEntries}"
                              SelectedItem="{Binding SpecialSignalEntrySelected}" Height="200">
            <xcdg:DataGridControl.Columns>
                <xcdg:Column FieldName="Name" Title="Type of special signal" ReadOnly="True"></xcdg:Column>
            </xcdg:DataGridControl.Columns>
        </xcdg:DataGridControl>
        </GroupBox>

        <GroupBox Header="Parameters" Grid.Row="1" Margin="0,3,0,0" Padding="5">
            <ContentControl Name="MyContentControl" 
                            DataContext="{Binding SpecialSignalEntrySelected, Mode=OneWay}" 
                            Content="{Binding SignalProviderSpecial}">
            </ContentControl>
        </GroupBox>
    </Grid>
</UserControl>