Question

I have a view which contains a ContentControl which has its ContentTemplate changed dynamically depending on a boolean property within the view model using a data trigger.

        <ContentControl>

            <!-- MyFirstControl user control by default-->
            <local:MyFirstControl/>

            <ContentControl.Style>
                <Style TargetType="ContentControl">                        
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSelected}"
                                     Value="True">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <!-- Different user control when trigger fired-->
                                        <local:MySecondControl />
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>

        </ContentControl>

The MySecondControl user control, which displays when the trigger is fired is intended to display a textblock, of which its Text property binds to a property also within the same view model.

I am obviously wrong, but my thinking was that the triggered control would inherit the same data context. Instead it is trying to use the MyFirstControl user control as its data context (I also receive this error: System.Windows.Data Error: 40 : BindingExpression path error:).

I have tried to explicitly state the data context of the triggered control with:

<local:MySecondControl DataContext="{Binding}"/>

However it is still using the default control (MyFirstControl) as its data context.

My question is, how do I force the triggered control to use the same data context as the view file it is within?

I am fairly new to the WPF scene so I hope this makes sense!

Thanks in advance.

Was it helpful?

Solution

There's a difference between Content and ContentTemplate.

Content is your actual content for the control, while ContentTemplate defines how to draw the Content

You are setting the Content property to MyFirstControl. Your trigger is changing the ContentTemplate property, so it is changing the way your Content (MyFirstControl) gets drawn so it is drawn using MySecondControl, however the Content itself is unchanged so the DataContext will still be your MyFirstControl.

You probably want to set the default ContentTemplate to MyFirstControl instead of the actual Content property.

<ContentControl>

    <ContentControl.Style>
        <Style TargetType="ContentControl">  
            <!-- Set default ContentTemplate -->
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <local:MyFirstControl />
                    </DataTemplate>
                </Setter.Value>
            </Setter>

            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSelected}"
                             Value="True">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <!-- Different user control when trigger fired-->
                                <local:MySecondControl />
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>

</ContentControl>

OTHER TIPS

Hope this will help:

<local:MySecondControl DataContext="{Binding Path=DataContext, 
                  RelativeSource={RelativeSource TemplatedParent}}"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top