Стилизация ListView.GroupStyle с помощью WrapPanel

#wpf #xaml #listview #styles #controltemplate

#wpf #xaml #listview #стили #controltemplate

Вопрос:

Хорошо, вот моя довольно простая проблема.

У меня есть ListView , который я оформил так, чтобы он выглядел как проводник Windows.

Теперь я хотел бы сгруппировать элементы внутри. Поэтому я определил a GroupStyle с помощью Expander , чтобы сгруппировать его. Теперь группировка выполнена нормально.

Что мне не нравится, так это то, что теперь my ListView отображает каждую группу в отдельной строке, в то время как я хотел бы иметь некоторую оболочку расширения, чтобы отображать много групп в одной строке.

Изображение лучше, чем какой-либо текст, я думаю.

Вот что у меня есть:

Что у меня есть

Вот что я хочу:

Чего я хочу

Я не могу найти, какое свойство мне следует стилизовать, чтобы GroupItems поместиться в WrapPanel, точно так же, как я сделал для элементов.

Вот мой стиль ListView:

 <ResourceDictionary>

                    <!-- Explorer-style layout-->
                    <DataTemplate x:Key="ExplorerView">
                        <StackPanel Orientation="Horizontal" Height="Auto" Width="150">
                            <Image Source="{Binding Path=Value.AppConfig.Appli.AppType, Converter={StaticResource TypeToIconConverter}}" Margin="5"
                                   Height="50" Width="50"/>
                            <StackPanel VerticalAlignment="Center" Width="90">
                                <TextBlock Text="{Binding Path=Value.AppConfig.Appli.AppName}" 
                     FontSize="13" HorizontalAlignment="Left" TextWrapping="WrapWithOverflow"
                     Margin="0,0,0,1" />
                                <TextBlock Text="{Binding Path=Value.AppConfig.Appli.AppType}" FontSize="9" 
                     HorizontalAlignment="Left" Margin="0,0,0,1" />
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>

                    <!-- Group header style-->
    <Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">


        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">

                    <Expander x:Name="exp" IsExpanded="True" Width="310"
                                   BorderBrush="CornflowerBlue">

                        <Expander.Header>
                            <DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                        Background="CornflowerBlue" x:Name="expContent"
                                        Width="{Binding RelativeSource={RelativeSource
                                            Mode=FindAncestor, AncestorType={x:Type Expander}},
                                            Path=Width}"
                                        Height="{Binding RelativeSource={RelativeSource
                                            Mode=FindAncestor, AncestorType={x:Type ToggleButton}},
                                            Path=ActualHeight}">
                                <CheckBox IsChecked="False" DockPanel.Dock="Right"/>
                                <TextBlock Text="{Binding Path=Name}" Foreground="White"
                                           FontWeight="Bold" HorizontalAlignment="Center" />
                            </DockPanel>
                        </Expander.Header>
                        <ItemsPresenter />
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>



                </ResourceDictionary>
    <!-- (...) -->

    <ListView ItemsSource="{Binding GroupedConfig, Mode=TwoWay}" 
              ItemTemplate="{StaticResource ExplorerView}">



        <ListView.ItemsPanel>
            <ItemsPanelTemplate >
                <WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
                     RelativeSource={RelativeSource 
                                     AncestorType=Expander}}"
                     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.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}" />
        </ListView.GroupStyle>


    </ListView>
  

Есть идеи?
Я пытаюсь вставить что-нибудь подходящее Setter в стиле, определенном для GroupItem , но я начинаю думать, что это неправильный способ сделать.

Спасибо!

Ответ №1:

Я, наконец, нашел нужное свойство для редактирования после многих попыток.

Я думаю, было бы полезно опубликовать это здесь, если кому-нибудь понадобится что-то сделать с таким же поведением:

Итак, у нас действительно есть свойство Panel в GroupStyle , в которое мы можем добавить это так необходимое WrapPanel :

 <ListView.GroupStyle>
    <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
        <GroupStyle.Panel>
            <ItemsPanelTemplate>
                <WrapPanel Width="800" />
            </ItemsPanelTemplate>
        </GroupStyle.Panel>
    </GroupStyle>
</ListView.GroupStyle>
  

Комментарии:

1. В .NET 4.5 больше нет необходимости добавлять GroupStyle. Панель, просто устанавливаю ListBox. ItemsPanel достаточно. Это может быть довольно неприятно, если вы разработали приложение под управлением .NET 4.5, а затем видите, что все испорчено на клиентах, которые только что запустили 4.0. MS добавила довольно много подводных камней с обновлением 4.5 на месте…

Ответ №2:

На случай, если кто-нибудь здесь, как я пытаюсь обернуть элементы списка, но на основе неизвестного количества элементов, поэтому вы не можете установить ширину, подобную приведенному выше ответу, вот как я это сделал.

 <ListBox.ItemsPanel>
<ItemsPanelTemplate>
    <WrapPanel Orientation="Vertical" MaxHeight="{Binding Converter={StaticResource ListBoxHeightToItemsPanelHeightConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}"/> 
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
  

В моем конвертере я просто вычитаю 30, чтобы учесть высоту заголовка.

Вот полный код:

 <ListBox.GroupStyle>
<GroupStyle>
    <GroupStyle.HeaderTemplate>
        <DataTemplate>
            <TextBlock Margin="8" FontSize="18" TextAlignment="Center" FontWeight="Bold" Foreground="White" >
                <TextBlock.Text>
                    <Binding Path="Name"/>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </GroupStyle.HeaderTemplate>
    <GroupStyle.Panel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
    <WrapPanel Orientation="Vertical" MaxHeight="{Binding Converter={StaticResource ListBoxHeightToGroupStyleHeightConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}"/> 
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
    <!-- Your template here. -->
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate >
    <!-- Your template here. -->
</DataTemplate>
</ListBox.ItemTemplate>
  

Надеюсь, это поможет кому-то сэкономить время!