问题
I have a ListView which layout looks like a Windows Explorer view (icon + some details), bound to a list somewhere in the ViewModel.
My aim here is to be able to switch between explorer view or classic view whenever we want.
I could define an ItemsPanelTemplate
doing exactly the work to display correctly the layout, directly in the ListView.ItemsPanel
field. Now, I'd like to define it in the resources so that I'll be able to use it in different views, and especially in one control, the user should have the choice between Explorer view or classic list view (the default rendering for a list)
How'd you do that? I cannot define any ItemsPanelTemplate
in my ResourceDictionary
, and if I define a DataTemplate
it is not compatible (while I thought that following pure logic, ItemsPanelTemplate
should inherit from DataTemplate
, but it actually doesn't look like so).
Code snippet for the actual list:
<ListView SelectionMode="Single"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Bottom"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ItemsSource="{Binding ListUserApps,
UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedUserApp, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="White">
<ListView.ItemsPanel>
<ItemsPanelTemplate >
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource
AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
<!--MinWidth="{Binding ItemWidth,
RelativeSource={RelativeSource Self}}"-->
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="Auto" Width="150">
<Image Source="{Binding Path=Appli.AppType, Converter={StaticResource TypeToIconConverter}}" Margin="5"
Height="50" Width="50"/>
<StackPanel VerticalAlignment="Center" Width="90">
<TextBlock Text="{Binding Path=Appli.AppName}"
FontSize="13" HorizontalAlignment="Left" TextWrapping="WrapWithOverflow"
Margin="0,0,0,1" />
<TextBlock Text="{Binding Path=Appli.AppType}" FontSize="9"
HorizontalAlignment="Left" Margin="0,0,0,1" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Keeping the ItemTemplate
in a static resource was easy to do, but now I can't do anything with the ItemsPanelTemplate
...
Any ideas? I'm using MVVM so I'm trying ideally not to use code-behind if possible
回答1:
you would use a style for the whole ListView for that.
so you would do:
<Grid.Resources>
<Style x:Key="ListViewStyle" TargetType="ListView">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate >
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource
AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
<!--MinWidth="{Binding ItemWidth,
RelativeSource={RelativeSource Self}}"-->
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ListView SelectionMode="Single"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Bottom"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ItemsSource="{Binding ListUserApps,
UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedUserApp, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="White" Style="{StaticResource ListViewStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="Auto" Width="150">
<Image Source="{Binding Path=Appli.AppType, Converter={StaticResource TypeToIconConverter}}" Margin="5"
Height="50" Width="50"/>
<StackPanel VerticalAlignment="Center" Width="90">
<TextBlock Text="{Binding Path=Appli.AppName}"
FontSize="13" HorizontalAlignment="Left" TextWrapping="WrapWithOverflow"
Margin="0,0,0,1" />
<TextBlock Text="{Binding Path=Appli.AppType}" FontSize="9"
HorizontalAlignment="Left" Margin="0,0,0,1" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
if you want the user then be able to switch between explorer and classic view, just define a second Style and switch the style of the listview. This can be done for example with some VisualStates and a 'DataStateBehavior'.
Alternatively you could create a style with some DataTriggers and Setters for the individual ItemsPanels.
来源:https://stackoverflow.com/questions/5705666/listview-define-itemspaneltemplate-in-resource-dictionary