简体   繁体   中英

Switch control template of listview when clicking a button

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>

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM