0

Is it possible to set the control template of my listview with xaml when I click a button?

Right now I know how to set my contenttemplate when I have my ListViewItem selected, but not how to change my control template when something outside of the listview changes.

I'd like to change my ListItemTemplate to use the RentTemplate or the BuyTemplate when clicking the corresponding button.

    <Button x:Name="RentButton" />
    <Button x:Name="BuyButton" />

    <ListView Name="ItemsList">
        <ListView.Resources>
            <!-- unselected item template -->
            <DataTemplate x:Key="DefaultItemTemplate">
            </DataTemplate>
            <!-- selected item template -->
            <DataTemplate x:Key="SelectedItemTemplate">
            </DataTemplate>
            <DataTemplate x:Key="RentTemplate">
            </DataTemplate>
            <DataTemplate x:Key="BuyTemplate">
            </DataTemplate>
        </ListView.Resources>
        <ListView.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <!-- set properties for all items -->
                <Setter Property="ContentTemplate" Value="{StaticResource DefaultItemTemplate}" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <!-- change what the selected item looks like -->
                        <Setter Property="ContentTemplate" Value="{StaticResource SelectedItemTemplate}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

Edit

I'm trying to use DataTriggers to select what template to use when I change a property (which I'll change when I click my buttons). I don't think this situation is ideal, but I don't know any other way.

The problem now is that I can't seem to mix Property triggers and DataTriggers in the same MultiTrigger.

The scenario I'm trying to make is the following: If I push the BuyButton I want to see the BuyTemplate. Same for RentButton with RentTemplate. BUT when I press a third button OverviewButton I'd like to make a choice between two templates, depending on whether the current ListBoxItem is selected or not.

Or am I misusing DataTemplates and DataTriggers and is there a better way to achieve this?

<Window.Resources>
    <!-- unselected item template -->
    <DataTemplate x:Key="DefaultItemTemplate">
    </DataTemplate>
    <!-- selected item template -->
    <DataTemplate x:Key="SelectedItemTemplate">
    </DataTemplate>
    <DataTemplate x:Key="RentTemplate">
    </DataTemplate>
    <DataTemplate x:Key="BuyTemplate">
    </DataTemplate>
    <Style x:Key="ListViewItemStyle" TargetType="{x:Type ListBoxItem}">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Property="IsSelected" Value="false"/>
                    <Condition Binding="{Binding SelectedType}" Value="Overview" />
                </MultiDataTrigger.Conditions>
                <Setter Property="ContentTemplate" Value="{StaticResource DefaultItemTemplate}" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Property="IsSelected" Value="true"/>
                    <Condition Binding="{Binding SelectedType}" Value="Overview" />
                </MultiDataTrigger.Conditions>
                <Setter Property="ContentTemplate" Value="{StaticResource SelectedItemTemplate}" />
            </MultiDataTrigger>
            <DataTrigger Binding="{Binding SelectedType}" Value="Rent">
                <Setter Property="ContentTemplate" Value="{StaticResource RentTemplate}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding SelectedType}" Value="Buy">
                <Setter Property="ContentTemplate" Value="{StaticResource BuyTemplate}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
Benjamin Diele
  • 1,177
  • 1
  • 10
  • 26
  • 1
    Seems you are searching for a `DataTemplateSelector`. See for example this tutorial: http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector – Flat Eric Dec 08 '14 at 17:42
  • 1
    @FlatEric: I'd post that as an answer, with an example of use. – Michael G Dec 08 '14 at 17:43

2 Answers2

2

You can use a DataTemplateSelector.
A tutorial can be found here: http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector

Some code from the tutorial:

public class ImgStringTemplateSelector : DataTemplateSelector
{
    public DataTemplate ImageTemplate { get; set; }
    public DataTemplate StringTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, 
        DependencyObject container)
    {
        String path = (string)item;
        String ext = System.IO.Path.GetExtension(path);
        if (System.IO.File.Exists(path) && ext == ".jpg")
            return ImageTemplate;
        return StringTemplate;
    }
}

XAML:

<Window.Resources>
    <local:RelativeToAbsolutePathConverter x:Key="relToAbsPathConverter" />

    <DataTemplate x:Key="stringTemplate">
      <TextBlock Text="{Binding}"/>
    </DataTemplate>

    <DataTemplate x:Key="imageTemplate">
      <Image Source="{Binding Converter={StaticResource relToAbsPathConverter}}" 
             Stretch="UniformToFill" Width="200"/>
    </DataTemplate>

    <local:ImgStringTemplateSelector 
        ImageTemplate="{StaticResource imageTemplate}" 
        StringTemplate="{StaticResource stringTemplate}" 
        x:Key="imgStringTemplateSelector" />
</Window.Resources>

<ListView ScrollViewer.CanContentScroll="False" 
          ItemsSource="{Binding ElementName=This, Path=PathCollection}" 
          ItemTemplateSelector="{StaticResource imgStringTemplateSelector}">
</ListView>

The templates and the selector can be specidifed in the resources, the control must then reference the DataTemplateSelector.

Flat Eric
  • 7,971
  • 9
  • 36
  • 45
  • How would I use my button click to change the selected template? I've read [in an other answer](http://stackoverflow.com/a/2089272/1653998) that choosing the template is an event that only happens once. – Benjamin Diele Dec 08 '14 at 19:25
  • Maybe this post will solve your problem: http://stackoverflow.com/questions/8715315/how-to-trigger-datatemplateselector-when-property-changes – Flat Eric Dec 08 '14 at 19:35
  • Eric, I've tried applying those suggestions and have edited my question. – Benjamin Diele Dec 08 '14 at 20:22
0

I've ultimately solved it like this:

    <Style x:Key="OverviewListViewItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="ContentTemplate" Value="{StaticResource DefaultItemTemplate}" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="true">
                <Setter Property="ContentTemplate" Value="{StaticResource SelectedItemTemplate}" />
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="BuyListViewItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="ContentTemplate" Value="{StaticResource BuyTemplate}" />
    </Style>
    <Style x:Key="RentListViewItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="ContentTemplate" Value="{StaticResource RentTemplate}" />
    </Style>

And just doing this in my view:

    private void RentButton_Click(object sender, RoutedEventArgs e)
    {
        ItemsList.ItemContainerStyle = (System.Windows.Style)Resources["RentListViewItemStyle"];
        _MainWindowViewModel.RentButton_Click();
    }

    private void BuyButton_Click(object sender, RoutedEventArgs e)
    {
        ItemsList.ItemContainerStyle = (System.Windows.Style)Resources["BuyListViewItemStyle"];
        _MainWindowViewModel.BuyButton_Click();
    }

    private void PropertyButton_Click(object sender, RoutedEventArgs e)
    {
        ItemsList.ItemContainerStyle = (System.Windows.Style)Resources["OverviewListViewItemStyle"];
        _MainWindowViewModel.PropertyButton_Click();
    }

This was the easiest way to switch styles without losing too much time with figuring out the right combination of voodoo and Triggers.

Benjamin Diele
  • 1,177
  • 1
  • 10
  • 26