Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing DataTemplates at runtime using DataTriggers

I'm trying to change a DataTemplate for objects in my WPF application according to a specific boolean value. When the value is "True" I want the DataTemplate to be something and when the value is "False" I want the DataTemplate to be something else.

I've tried writing this code, but so far I end up with an annoying "Out of Memory exception".

<DataTemplate DataType="{x:Type vm:MyObjectViewModel}">
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Visible}" Value="False">
            <Setter TargetName="MainTemplateGrid" Property="Content">
                <Setter.Value>
                    <Ellipse Width="50" Height="50" Fill="Red" />
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Visible}" Value="True">
            <Setter TargetName="MainTemplateGrid" Property="Content">
                <Setter.Value>
                    <Image Source="{Binding Icon}" Opacity="{Binding Visible, Converter={StaticResource VisibilityConverter}}" />
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </DataTemplate.Triggers>
    <ContentControl x:Name="MainTemplateGrid" />
</DataTemplate>

If anyone has a clue on how to fix this, please let me know.

like image 461
Jonathan Perry Avatar asked Oct 22 '22 17:10

Jonathan Perry


2 Answers

I figured it out.

I did this using a ContentControl and by setting its Style using the DataTriggers, here's the code:

 <DataTemplate DataType="{x:Type vm:MyControlViewModel}">
    <ContentControl>
        <ContentControl.ToolTip>
           <!-- TOOLTIP CODE GOES HERE -->
        </ContentControl.ToolTip>
        <ContentControl.InputBindings>
            <!-- INPUT BINDINGS CODE GOES HERE -->
        </ContentControl.InputBindings>
        <ContentControl.ContextMenu>
            <!-- CONTEXT MENU CODE GOES HERE -->
        </ContentControl.ContextMenu>
        <ContentControl.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger Binding="Visibility" Value="0">
                        <Setter Property="ContentControl.Content">
                            <Setter.Value>
                                <Ellipse Width="50" Height="50" Opacity="0.5">
                                    <Ellipse.Fill>
                                        <LinearGradientBrush>
                                            <GradientStopCollection>
                                                <GradientStop Color="Red" Offset="0" />
                                                <GradientStop Color="DarkRed" Offset="0.8" />
                                            </GradientStopCollection>
                                        </LinearGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="Visibility" Value="100">
                        <Setter Property="ContentControl.Content">
                            <Setter.Value>
                                <Image Source="{Binding Icon}" Opacity="{Binding Visible, Converter={StaticResource VisibilityConverter}}" />
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</DataTemplate>
like image 97
Jonathan Perry Avatar answered Oct 30 '22 02:10

Jonathan Perry


You should be able to use a data template selector (see DataTemplateSelector and Data Templating Overview) and apply it to the appropriate template selector property (e.g. Button has a ContentTemplateSelector property).

like image 38
Alan Bradbury Avatar answered Oct 30 '22 04:10

Alan Bradbury