ListView: define ItemsPanelTemplate in resource dictionary

折月煮酒 提交于 2019-12-10 03:30:40

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!