Search code examples
wpf-controlsmvvm-lightdatatemplate

WPF MVVM how to bind ContentTemplate dynamically


(WPF MVVM) I am trying to make a Pause/Play button using my own Style and combination of ContentTemplate->StaticResource->DataTemplate. I set the DataTemplate to a vector graphic data. I have prepared 2 vector graphics for Pause-Button and for Play-Button. My target: if I click the Pause-button the ContentTemplate will be "switched" to Play-Button-DataTemplate and the button becomes Play-Button. I know that I need to bind Click-event of the button or use RelayCommand to do Pause/Play operation (in my code snippet I have not bound the Click event), but I don't know how to bind the ContentTemplate to get the effect I need. Thank you in advance.

<controls:MyButton x:Name="btnPause" AutomationProperties.Name="btnPause" Style="{StaticResource MyButtonStyle}" ContentTemplate="{StaticResource dtmpPause}" />

<DataTemplate x:Name="dtmpPause">
        <Path x:Name="pathPause" Fill="White" Stretch="Uniform" Data="M314.00598,126.271 L379.52698,126.271 L379.52698,440.672 L314.00598,440.672 z M187.40198,126.271 L252.92398,126.271 L252.92398,440.672 L187.40198,440.672 z M283.45901,34.240997 C146.03,34.240997 34.229004,146.043 34.229004,283.45697 C34.229004,420.88702 146.03,532.70099 283.45901,532.70099 C420.88699,532.70099 532.70203,420.88702 532.70203,283.45697 C532.70203,146.043 420.88699,34.240997 283.45901,34.240997 z M283.45901,0 C439.772,0 566.92999,127.158 566.92999,283.45697 C566.92999,439.771 439.772,566.94299 283.45901,566.94299 C127.15799,566.94299 0,439.771 0,283.45697 C0,127.158 127.15799,0 283.45901,0 z"/>
</DataTemplate>

<DataTemplate x:Name="dtmpPlay">
    <Path x:Name="pathPlay" Fill="White" Stretch="Uniform" Data="M269.00003,121.50002 L298.00003,121.50002 L298.00003,445.50003 L269.00003,445.50003 z M283.5,41.621429 L41.620132,283.50198 L283.5,525.37958 L525.37982,283.50198 z M283.5,0 L566.99994,283.50198 L283.5,567 L0,283.50198 z"/>
</DataTemplate>

Solution

  • Use DataTemplateSelector which allows you to pick the DataTemplate you wish by defined condition, which you implement however you wish.

    Here is an example:

    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;
    
            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;
    
                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }
    
            return null;
        }
    }
    

    in this example you return whatever DataTemplate you wish based on what priority your DataContext has.

    In xaml you will need to tell the control what DataTemplateSelector it should use:

    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"
             ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
             HorizontalContentAlignment="Stretch"/>
    

    In this case myDataTemplateSelector will be used by the ListBox.

    In your case its the MyButton.