locked
How to adjust the width of group header in ListView to stretch full width? RRS feed

  • Question

  • I am using CollectionViewSource and HeaderTemplate to show grouped items in a ListView (Windows store app, WinRT 8.1, VS2013 C#).

    I want the width of the group header of the HeaderTemplate to stretch to the full width of the ListView. I have tried to binding the width of the root element(which is a panel) of the  HeaderTemplate to the ActualWidth of the named ListView, it did not work(Well, it did work somehow, but with a huge problem - the top group header would not display itself). Here is my source code:

    [MainPage.xaml]

    <Page x:Class="App8.MainPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:App8">
    
        <Page.Resources>
            <CollectionViewSource x:Name="myCVS"
                                  IsSourceGrouped="true" />
        </Page.Resources>
    
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <ListView x:Name="lbxHouseGuests"
                      Width="600"
                      Height="500"
                      Margin="50"
                      ItemsSource="{Binding Source={StaticResource myCVS}}"
                
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding FirstName}" />
                            <TextBlock Text="{Binding LastName}" />
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
                
                <ListView.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.HeaderTemplate>
                            <DataTemplate>
                                <StackPanel HorizontalAlignment="Stretch"
                                            x:Name="MyPanel"
                                            Background="Red"
                                            Width="{Binding ActualWidth, ElementName=lbxHouseGuests}">
                                    <Button Content="{Binding Key}"
                                            HorizontalAlignment="Stretch" />
                                </StackPanel>
                            </DataTemplate>
                        </GroupStyle.HeaderTemplate>
                    </GroupStyle>
                </ListView.GroupStyle>
            </ListView>
        </Grid>
    </Page>

    [MainPage.xaml.cs]

    using System.Collections.Generic;
    using System.Linq;
    using Windows.UI.Xaml.Controls;
    
    
    namespace App8
    {
        public class HouseGuest
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Role { get; set; }
        }
    
    
        public sealed partial class MainPage : Page
        {
    
            public MainPage()
            {
                this.InitializeComponent();
    
                List<HouseGuest> ls = new List<HouseGuest>();
                ls.Add(new HouseGuest() { FirstName = "Britney", LastName = "Haynes", Role = "Coach" });
                ls.Add(new HouseGuest() { FirstName = "Britney", LastName = "Haynes", Role = "Coach" });
                ls.Add(new HouseGuest() { FirstName = "Britney", LastName = "Haynes", Role = "Coach" });
                ls.Add(new HouseGuest() { FirstName = "Ian", LastName = "Terry", Role = "Player" });
                ls.Add(new HouseGuest() { FirstName = "Ian", LastName = "Terry", Role = "Player" });
                ls.Add(new HouseGuest() { FirstName = "Ian", LastName = "Terry", Role = "Player" });
                ls.Add(new HouseGuest() { FirstName = "Ian", LastName = "Terry", Role = "Player" });
    
                myCVS.Source = from g in ls group g by g.Role into grp orderby grp.Key select grp;
            }
        }
    }
     

    Another possible solution is to progmatically adjust the width of the root panel(i.e, myPanel) in the ListView's SizeChanged event handle. But to do this, I need to traverse the group items of listview and set the width of "myPanel" for each group. But I have absolutely no idea how to access "myPanel" in the group item which is generated by my HeadTemplate. That's my question. Any idea would be appreciated.



    Monday, November 4, 2013 1:48 AM

Answers

  • The default generated ContentPresenter has its HorizontalAlignment set to Left. You could specify your own ContainerStyle for the GroupItems and set the HorizontalContentAlignment property of the ContentControl to Stretch to change this:

    <ListView.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.ContainerStyle>
                            <Style TargetType="GroupItem">
                                <Setter Property="IsTabStop" Value="False"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="GroupItem">
                                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                                <Grid>
                                                    <Grid.RowDefinitions>
                                                        <RowDefinition Height="Auto"/>
                                                        <RowDefinition Height="*"/>
                                                    </Grid.RowDefinitions>
                                                    <ContentControl x:Name="HeaderContent" ContentTemplate="{TemplateBinding ContentTemplate}"
                                                                    HorizontalContentAlignment="Stretch"
                                                                    ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" 
                                                                    Content="{TemplateBinding Content}" IsTabStop="False" Margin="{TemplateBinding Padding}" TabIndex="0"/>
                                                    <ItemsControl x:Name="ItemsControl" IsTabStop="False" ItemsSource="{Binding GroupItems}" Grid.Row="1" TabIndex="1" TabNavigation="Once">
                                                        <ItemsControl.ItemContainerTransitions>
                                                            <TransitionCollection>
                                                                <AddDeleteThemeTransition/>
                                                                <ContentThemeTransition/>
                                                                <ReorderThemeTransition/>
                                                                <EntranceThemeTransition IsStaggeringEnabled="False"/>
                                                            </TransitionCollection>
                                                        </ItemsControl.ItemContainerTransitions>
                                                    </ItemsControl>
                                                </Grid>
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </GroupStyle.ContainerStyle>
                        <GroupStyle.HeaderTemplate>
                            <DataTemplate>
                                <StackPanel HorizontalAlignment="Stretch"
                                                x:Name="MyPanel"
                                                Background="Red">
                                    <Button Content="{Binding Key}"
                                                HorizontalAlignment="Stretch" />
                                </StackPanel>
                            </DataTemplate>
                        </GroupStyle.HeaderTemplate>
                    </GroupStyle>
                </ListView.GroupStyle>
    

    Monday, November 4, 2013 10:50 AM

All replies

  • The default generated ContentPresenter has its HorizontalAlignment set to Left. You could specify your own ContainerStyle for the GroupItems and set the HorizontalContentAlignment property of the ContentControl to Stretch to change this:

    <ListView.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.ContainerStyle>
                            <Style TargetType="GroupItem">
                                <Setter Property="IsTabStop" Value="False"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="GroupItem">
                                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                                <Grid>
                                                    <Grid.RowDefinitions>
                                                        <RowDefinition Height="Auto"/>
                                                        <RowDefinition Height="*"/>
                                                    </Grid.RowDefinitions>
                                                    <ContentControl x:Name="HeaderContent" ContentTemplate="{TemplateBinding ContentTemplate}"
                                                                    HorizontalContentAlignment="Stretch"
                                                                    ContentTransitions="{TemplateBinding ContentTransitions}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" 
                                                                    Content="{TemplateBinding Content}" IsTabStop="False" Margin="{TemplateBinding Padding}" TabIndex="0"/>
                                                    <ItemsControl x:Name="ItemsControl" IsTabStop="False" ItemsSource="{Binding GroupItems}" Grid.Row="1" TabIndex="1" TabNavigation="Once">
                                                        <ItemsControl.ItemContainerTransitions>
                                                            <TransitionCollection>
                                                                <AddDeleteThemeTransition/>
                                                                <ContentThemeTransition/>
                                                                <ReorderThemeTransition/>
                                                                <EntranceThemeTransition IsStaggeringEnabled="False"/>
                                                            </TransitionCollection>
                                                        </ItemsControl.ItemContainerTransitions>
                                                    </ItemsControl>
                                                </Grid>
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </GroupStyle.ContainerStyle>
                        <GroupStyle.HeaderTemplate>
                            <DataTemplate>
                                <StackPanel HorizontalAlignment="Stretch"
                                                x:Name="MyPanel"
                                                Background="Red">
                                    <Button Content="{Binding Key}"
                                                HorizontalAlignment="Stretch" />
                                </StackPanel>
                            </DataTemplate>
                        </GroupStyle.HeaderTemplate>
                    </GroupStyle>
                </ListView.GroupStyle>
    

    Monday, November 4, 2013 10:50 AM
  • Hi,Magnus, I've test your solution, but it still won't work. This seems going in the right direction, but I can't figure out what's wrong(I just copy and paste the above ContainerStyle into my code). Would you mind run a test of the above code for me?  
    Monday, November 4, 2013 12:01 PM
  • This is what it looks like on my computer:

    Isn't this what you wanted? Try to make some changes to the ControlTemplate of the GroupItem to see if anything changes.

    Monday, November 4, 2013 12:17 PM
  • Oh, my, that is what I want exactly!

    But it still won't work on my computer(Windows 8.1, VS2013).


    Edit:

    I just found this page: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.groupstyle.containerstyle

    Behind the title, it said:[ContainerStyle may be altered or unavailable for releases after Windows 8.1 and is not supported forItemsControl.GroupStyle.]

    Is this the reason why it won't work on my computer?

    If so, is there any workground? Really stuck here.

    Edit:

    Finally, I got it worked. All I need to do is add this code:

                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel></VirtualizingStackPanel>
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>

    As it turns out, ContainerStyle is no longer honored on Windows 8.1 when ItemsPanel is an ItemsStackPanel(which is the default). So to make ContainerStyle effect, we need to change ItemPanel from default value to something else.

    More explains:

    http://msdn.microsoft.com/en-us/library/windows/apps/dn263110.aspx 


    • Edited by silverbird.lee Monday, November 4, 2013 1:03 PM
    • Proposed as answer by aiyaiya Wednesday, November 6, 2013 2:31 AM
    Monday, November 4, 2013 12:30 PM
  • HI,I just us this code for my window phone 8.1 App.

    And i need to show group key list like system app list page.just like you,show the "Coach ,player.." when you touch the group title .

    As i know the window phone 8 can do this by use LongListSelector

    (http://msdn.microsoft.com/en-us/library/windowsphone/design/jj735577(v=vs.105).aspx),but not support on wp 8.1.

    So do you have some idea about this ???

    Thanks.


    • Edited by liupenng Tuesday, April 15, 2014 5:26 AM
    • Proposed as answer by Sean Bennett Monday, April 21, 2014 10:38 AM
    • Unproposed as answer by Sean Bennett Monday, April 21, 2014 10:39 AM
    Tuesday, April 15, 2014 5:25 AM
  • YES! Thanks so very much, adding the VirtualizingStackPanel works (I'm on Windows Phone 8.1 WinRT)
    Thursday, July 10, 2014 4:59 PM