ListView: define ItemsPanelTemplate in resource di

2019-04-24 10:43发布

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条回答
干净又极端
2楼-- · 2019-04-24 11:44

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.

查看更多
登录 后发表回答