2

I have a ListView that is grouped with headers. I have one UserControl for the header <local:MyHeaderUserControl /> that displays the header using a text block <TextBlock Text="{Binding Key}" /> and another UserControl for each entry <local:MyListItemUserControl> that binds to the listed object.

I want to display them full width with no margins. ListView in UWP inserts annoying margins, divider lines and by default aligns left and it is not clear which properties I have to set on which of the many possible templates will remove those.

What is the minimal template for doing this?

Note: I have already worked this out and am hoping to post for reference when I can but am happy to let someone else get the karma if they get there first ;)

Brendan
  • 18,771
  • 17
  • 83
  • 114
  • Maybe [this](https://stackoverflow.com/a/38151627/6843321) could help. – Marian Dolinský Oct 08 '17 at 10:48
  • Thanks, that is part of the solution but the group header template is more complicated and the default GroupStyles insert loads of hard coded margins, what’s more is the old ContainerStyle used in Windows 8 is deprecated in UWP which tripped me up when updating my code – Brendan Oct 08 '17 at 10:53

3 Answers3

2

Here's an easier way: declare a Style for your ListView.

Example XAML for ListView:

<ListView 
  ItemContainerStyle="{StaticResource ListViewItemStretchStyle}"
  ...
</ListView>

And here's the Style:

<Style x:Key="ListViewItemStretchStyle" TargetType="ListViewItem">
  <Setter Property="HorizontalContentAlignment" Value="Stretch" />
  <Setter Property="Margin" Value="0" />
  <Setter Property="Padding" Value="0" />
</Style>

I also included Stretch, since that is commonly desired for ListView usages.

You can include the Style in the Page containing the ListView. Just be sure to declare it before the ListView declaration.

Peri Hartman
  • 19,314
  • 18
  • 55
  • 101
1

This is the most minimal template I could find, but it also removes the default styling for focus, selection, animations etc. which would all have to be handled in the custom UserControls ...

<ListView
    ItemsSource="{Binding Source={StaticResource collectionViewSource}}"
    >
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <local:MyListItemUserControl />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderContainerStyle>
                <Style TargetType="ListViewHeaderItem">
                    <Setter Property="Margin" Value="0" />
                    <Setter Property="Padding" Value="0" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListViewHeaderItem">
                                <local:MyHeaderUserControl />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.HeaderContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
</ListView>

Alternatively, this template preserves the default behaviours for clicking, selecting etc. whilst removing the margins and making the controls full width ...

<ListView
    ItemsSource="{Binding Source={StaticResource collectionViewSource}}"
    >
    <ListView.ItemTemplate>
        <DataTemplate>
            <!-- This is marginless and full width! -->
            <local:MyListItemUserControl />
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
            <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
            <Setter Property="Background" Value="{ThemeResource ListViewItemBackground}"/>
            <Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}"/>
            <Setter Property="TabNavigation" Value="Local"/>
            <Setter Property="IsHoldingEnabled" Value="True"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
            <Setter Property="MinHeight" Value="0"/>
            <Setter Property="AllowDrop" Value="False"/>
            <Setter Property="UseSystemFocusVisuals" Value="True"/>
            <Setter Property="FocusVisualMargin" Value="0"/>
            <Setter Property="FocusVisualPrimaryBrush" Value="{ThemeResource ListViewItemFocusVisualPrimaryBrush}"/>
            <Setter Property="FocusVisualPrimaryThickness" Value="2"/>
            <Setter Property="FocusVisualSecondaryBrush" Value="{ThemeResource ListViewItemFocusVisualSecondaryBrush}"/>
            <Setter Property="FocusVisualSecondaryThickness" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <ListViewItemPresenter CheckBrush="{ThemeResource ListViewItemCheckBrush}" ContentMargin="{TemplateBinding Padding}" CheckMode="{ThemeResource ListViewItemCheckMode}" ContentTransitions="{TemplateBinding ContentTransitions}" CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}" DragForeground="{ThemeResource ListViewItemDragForeground}" DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}" DragBackground="{ThemeResource ListViewItemDragBackground}" DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" FocusVisualPrimaryBrush="{TemplateBinding FocusVisualPrimaryBrush}" FocusVisualSecondaryThickness="{TemplateBinding FocusVisualSecondaryThickness}" FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}" FocusVisualMargin="{TemplateBinding FocusVisualMargin}" FocusVisualPrimaryThickness="{TemplateBinding FocusVisualPrimaryThickness}" FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}" FocusVisualSecondaryBrush="{TemplateBinding FocusVisualSecondaryBrush}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Control.IsTemplateFocusTarget="True" PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}" PressedBackground="{ThemeResource ListViewItemBackgroundPressed}" PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}" PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}" ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}" SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}" SelectedForeground="{ThemeResource ListViewItemForegroundSelected}" SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}" SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </ListView.ItemContainerStyle>
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <!-- This is marginless and full width! -->
                    <local:MyHeaderUserControl />
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
            <GroupStyle.HeaderContainerStyle>
                <Style TargetType="ListViewHeaderItem">
                    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
                    <Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}"/>
                    <Setter Property="Background" Value="{ThemeResource ListViewHeaderItemBackground}"/>
                    <Setter Property="Margin" Value="0"/>
                    <Setter Property="Padding" Value="0"/>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="VerticalContentAlignment" Value="Top"/>
                    <Setter Property="MinHeight" Value="0"/>
                    <Setter Property="UseSystemFocusVisuals" Value="True"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListViewHeaderItem">
                                <StackPanel BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                    <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </StackPanel>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.HeaderContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
</ListView>
Brendan
  • 18,771
  • 17
  • 83
  • 114
0

The reason why this happens is that every time you add something that is not a ListViewitem its automatically wrapped around a ListViewItem and a rough 10 margin is applied left and right to it.

Be a smart player play easy and dirty.

Instead of bothering with 100 lines of styling xalm lines you can just apply a negative -10 margin left and right of your custom item. this will force the list item to cover this 10 px margin that listview automatically applies.

this of course implies that you will first create a listviewitem and then set the content of this listviewitem to your custom item, lastly add listviewitem to your ListView.

        MyListItemUserControl item = new MyListItemUserControl();
        item.Height = 45;
        item.Margin = new Thickness(-10, 4, -10, 4);
        item.HorizontalAlignment = HorizontalAlignment.Stretch;

        ListViewItem ListItem  = new ListViewItem();
        ListItem.HorizontalAlignment = 
        HorizontalAlignment.Stretch;
        ListItem.HorizontalContentAlignment = HorizontalAlignment.Stretch;
        ListItem.Content =item;
        LIST.Items.Add(ListItem);
Xeorge Xeorge
  • 452
  • 4
  • 10