2010-11-10 56 views
2

我有一個列表視圖和2個資源來顯示列表視圖:BooksGridView & ImageDetailView。WPF:通過DataTrigger設置ListView視圖

ViewModel有一個名爲ViewMode的字符串屬性,它包含我當前想要顯示的視圖的名稱。 (它從另一個控件,使用工具欄更改)

我試圖通過使用DataTrigger來更改選定的視圖,但我似乎無法使View屬性發生更改。

當我直接設置視圖資源時,顯示正確的視圖。我還添加了背景更改以確保數據觸發器已激活,並且背景確實發生了變化。

所以我缺少明顯的東西在這裏...

<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> 

感謝

回答

12

基於MSDN上的示例,下面的工作是基於ViewModel中的更改來更改視圖。我可以用你的代碼中看到的唯一的區別是使用的DynamicResource

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類:

<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 [email protected]}" Margin="6,6,6,9"/> 
      </Grid> 
      <TextBlock Text="{Binding [email protected]}" FontSize="13" 
        HorizontalAlignment="Center" Margin="0,0,0,1" /> 
      <TextBlock Text="{Binding [email protected]}" FontSize="9" 
        HorizontalAlignment="Center" Margin="0,0,0,1" /> 
     </StackPanel> 
     </DataTemplate> 

     <DataTemplate x:Key="iconTemplate"> 
     <DockPanel Height="33" Width="150"> 
      <Image Source="{Binding [email protected]}" Margin="2"/> 
      <TextBlock DockPanel.Dock="Top" Text="{Binding [email protected]}" 
        FontSize="13" HorizontalAlignment="Left" 
        Margin="0,0,0,1" /> 
      <TextBlock Text="{Binding [email protected]}" 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 [email protected]}"/> 
     </StackPanel> 
     </DataTemplate> 

     <GridView x:Key="gridView"> 
     <GridViewColumn CellTemplate="{StaticResource checkbox}"/> 
     <GridViewColumn Header="Name" DisplayMemberBinding="{Binding [email protected]}"/> 
     <GridViewColumn Header="Type" DisplayMemberBinding="{Binding [email protected]}"/> 
     <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.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)); 
     } 
    } 
} 
+0

感謝!,兩個改變使它工作:第一個是DynamicResource,第二個是刪除ListView下的初始View定義。 – Amirshk 2010-11-15 23:48:33

+0

很高興幫助:) – Grammarian 2010-11-16 10:11:47

+0

你可以發佈MSDN示例的href: – Amirshk 2010-11-16 17:52:31

0

我看不到你的代碼中的任何明顯的問題你提供。我通常會建議檢查是否觸發了DataTrigger,但是您已經使用Background屬性測試了該屬性。

查看MSDN示例(link),實現中的唯一區別是,在示例中,切換ListView.View在代碼中進行了更改。

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

...

嗯,也許認爲資源可能無法發現的,它是失敗的。

...

我所能建議的只是看樣品。對不起沒有更多的幫助。

+0

TNX,但我做了通過設置導致異常的非法值可以確定資源。所以它似乎找到了資源,甚至激活了觸發器,但由於某種原因,視圖沒有改變。 – Amirshk 2010-11-10 23:29:24