代码之家  ›  专栏  ›  技术社区  ›  Amirshk

WPF:通过DataTrigger设置ListView视图

  •  2
  • Amirshk  · 技术社区  · 14 年前

    ViewModel有一个名为ViewMode的字符串属性,该属性包含当前要显示的视图的名称。(使用工具栏从另一个控件更改)

    我正试图通过使用 DataTrigger

    当我直接设置视图资源时,将显示正确的视图。我还添加了后台更改以确保数据触发器被激活,并且后台确实发生了更改。

    所以很明显我在这里漏掉了一些东西。。。

    <UserControl x:Class="eLibrary.View.FilteredBooksView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:Converters="clr-namespace:eLibrary.Converters"
                 xmlns:Controls="clr-namespace:eLibrary.Controls"
                 xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
                 xmlns:local="clr-namespace:eLibrary"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.Resources>
            <Converters:CoverImageConverter x:Key="CoverImageConverter"/>
            <BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
    
            <GridView x:Key="BooksGridView">
                ...
            </GridView>
    
            <Controls:TileView x:Key="ImageDetailView">
                ...
            </Controls:TileView>
    
            <CollectionViewSource x:Key="sortedBooks" Source="{Binding Books}">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="Title" Direction="Ascending"/>
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
    
            <Style TargetType="{x:Type ListView}">
                <Style.Triggers>
    
                    <DataTrigger Binding="{Binding Path=ViewMode}" Value="BooksGridView">
                        <Setter Property="View" Value="{StaticResource BooksGridView}"/>
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
    
                    <DataTrigger Binding="{Binding Path=ViewMode}" Value="ImageDetailView">
                        <Setter Property="View" Value="{StaticResource ImageDetailView}" />
                        <Setter Property="Background" Value="Blue"/>
                    </DataTrigger>
    
                </Style.Triggers>
            </Style>
    
        </UserControl.Resources>
    
        <ListView
            VerticalAlignment="Stretch"
            Name="BooksListView"
            View="{StaticResource BooksGridView}"
            SelectionMode="Extended"
            ItemsSource="{Binding Source={StaticResource sortedBooks}}">
            <ListView.Resources>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                    <Setter Property="Visibility" Value="{Binding Path=ShouldDisplay, Converter={StaticResource BoolToVisConverter} }" />
                </Style>
            </ListView.Resources>
        </ListView>
    
    </UserControl>
    

    2 回复  |  直到 14 年前
        1
  •  14
  •   Grammarian    14 年前

    基于MSDN上的示例,下面的工作是根据ViewModel中的更改来更改视图。我能看到你的代码的唯一区别是 DynamicResource

    <Window x:Class="SDKSample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Custom View" 
        xmlns:l="clr-namespace:SDKSample" 
        Width="400" Height="500"
        SourceInitialized="Window_SourceInitialized">
    
        <Window.Resources>
    
          <DataTemplate x:Key="centralTile">
            <StackPanel Height="100" Width="90">
              <Grid Width="70" Height="70" HorizontalAlignment="Center">
                <Image Source="{Binding XPath=@Image}" Margin="6,6,6,9"/>
              </Grid>
              <TextBlock Text="{Binding XPath=@Name}" FontSize="13" 
                         HorizontalAlignment="Center" Margin="0,0,0,1" />
              <TextBlock Text="{Binding XPath=@Type}" FontSize="9" 
                         HorizontalAlignment="Center" Margin="0,0,0,1" />
            </StackPanel>
          </DataTemplate>
    
          <DataTemplate x:Key="iconTemplate">
            <DockPanel Height="33" Width="150">
              <Image Source="{Binding XPath=@Image}" Margin="2"/>
              <TextBlock DockPanel.Dock="Top" Text="{Binding XPath=@Name}" 
                         FontSize="13" HorizontalAlignment="Left" 
                         Margin="0,0,0,1" />
              <TextBlock Text="{Binding XPath=@Type}" FontSize="9" 
                         HorizontalAlignment="Left" Margin="0,0,0,1" />
            </DockPanel>
          </DataTemplate>
    
          <DataTemplate x:Key="checkbox">
            <CheckBox IsChecked="{Binding IsSelected, RelativeSource= {RelativeSource AncestorType=ListViewItem}}" 
                      Margin="0,1,1,1" >
            </CheckBox>
          </DataTemplate>
    
          <XmlDataProvider x:Key="myXmlDataBase" XPath="/myXmlData">
            <x:XData>
              <myXmlData xmlns="">
                <Item Name = "Fish" Type="fish" Image="images\fish.png"/>
                <Item Name = "Dog" Type="animal" Image="images\dog.png"/>
                <Item Name = "Flower" Type="plant" Image="images\flower.jpg"/>
                <Item Name = "Cat" Type="animal" Image="images\cat.png"/>
              </myXmlData>
            </x:XData>
          </XmlDataProvider>
    
          <DataTemplate x:Key="DisplayImage">
            <StackPanel Width="50">
              <Image Source="{Binding XPath=@Image}"/>
            </StackPanel>
          </DataTemplate>
    
          <GridView x:Key="gridView">
            <GridViewColumn CellTemplate="{StaticResource checkbox}"/>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding XPath=@Name}"/>
            <GridViewColumn Header="Type" DisplayMemberBinding="{Binding XPath=@Type}"/>
            <GridViewColumn Header="Image" CellTemplate="{StaticResource DisplayImage}"/>
          </GridView>
          <l:PlainView x:Key="tileView" ItemTemplate="{StaticResource centralTile}" ItemWidth="100"/>
          <l:PlainView x:Key="iconView" ItemTemplate="{StaticResource iconTemplate}"  ItemWidth="150"/>
    
        <Style TargetType="{x:Type ListView}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=ViewName}" Value="iconView">
                    <Setter Property="View" Value="{DynamicResource iconView}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=ViewName}" Value="tileView">
                    <Setter Property="View" Value="{DynamicResource tileView}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=ViewName}" Value="gridView">
                    <Setter Property="View" Value="{DynamicResource gridView}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    
        </Window.Resources>
    
      <StackPanel>
        <ListView Name="lv"
                  ItemsSource="{Binding Source={StaticResource myXmlDataBase}, XPath=Item}" 
                  FontSize="12" 
                  Background="LightBlue" >
          <ListView.ContextMenu>
            <ContextMenu>
              <MenuItem Header="gridView" Click="SwitchViewMenu"/>
              <MenuItem Header="iconView" Click="SwitchViewMenu"/>
              <MenuItem Header="tileView" Click="SwitchViewMenu"/>
            </ContextMenu>
          </ListView.ContextMenu>
    
    
        </ListView>
        <TextBlock FontSize="16" Foreground="Blue">
          CurrentView: <TextBlock Name="currentView" Text="{Binding Path=ViewName}"/>
        </TextBlock>
        <TextBlock>
          Right-click in the content window to change the view.
          </TextBlock>
    
      </StackPanel>
     </Window>
    

    using System;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace SDKSample
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
    
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
            public MainViewModel ViewModel
            {
                get { return this.DataContext as MainViewModel; }
            }
    
            void SwitchViewMenu(object sender, RoutedEventArgs args)
            {
                MenuItem mi = (MenuItem)sender;
                ViewModel.ViewName = mi.Header.ToString();
            }
    
            private void Window_SourceInitialized(object sender, EventArgs e)
            {
                ViewModel.ViewName = "gridView";
            }
        }
    }
    

    最后是ViewModel类:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    
    namespace SDKSample
    {
        public class MainViewModel : INotifyPropertyChanged
        {
            public string ViewName
            {
                get { return viewName; }
                set
                {
                    if (viewName == value)
                        return;
    
                    viewName = value;
                    NotifyPropertyChanged("ViewName");
                }
            }
            private string viewName;
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            void NotifyPropertyChanged(string name)
            {
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }
    
        2
  •  0
  •   Dennis    14 年前

    我看不出你提供的代码有什么明显的问题。我通常建议检查一下 DataTrigger 正在触发,但是您已经用 Background 财产。

    查看MSDN上的样本( link )实现的唯一区别是,在示例中,切换 ListView.View 在代码中更改。

    BookListView.View = this.FindResource("BooksGridView") as ViewBase;
    

    ...

    嗯,也许视图资源找不到,它正在失败。

    我只能建议你看看样品。很抱歉帮不上忙。