Solved: How to use one line per item in a UWP XAML ListView

 

Previous:

 

The previous 2 articles in this series examined ListView line spacing in a UWP XAML app. The list was an Observable Collection and so data binding was used. The main objective was to minimize the template height and padding for the list elements, especially when the item template only required content on a single Grid or StackPanel row. It was then concluded that the minimum vertical space in the list for each item, after padding etc. was zeroed in the item template was 2 lines, or rows.

 

The scenario considered was where a list of properties as name-value pairs was to be displayed as an outcome of a query to a Bluetooth (BLE) device, as to its device properties. Although there is a standard set of BLE device properties, few are mandatory and so the number of items returned from the query is not fixed. That is, the collection length and property names used are only determined at runtime. Hence the list UI needs to be determined dynamically through data binding or a code behind loop.

 

In the rush to minimise line spacing in a list it is worth considering what is being displayed and its purpose. For the case in point, the properties displayed were as information only and so do not require further interrogation. i.e. There was no need for the UI to support their selection, especially via touch. So the single line spacing in the UI for the collection items is suitable. If though touch is to be used to select items in a list, the UI does need a minimum of two lines per item.

 

A partial solution was provided in the first article where the padding was reduced to zero using a ListView.ItemContainerStyle :

<ListView x:Name="ListDeviceProperties" ItemsSource="{Binding ListProperties}"   >                    
      <ListView.ItemContainerStyle>
          <Style TargetType="ListViewItem">
              <Setter Property="Padding" Value="0" />
              <Setter Property="Margin" Value="0" />
              <Setter Property="BorderThickness" Value="0" />
                  <Setter Property="VerticalContentAlignment" Value="Center" />
                  <Setter Property="Template">
                  <Setter.Value>
                      <ControlTemplate TargetType="ListViewItem">
                          <ListViewItemPresenter ContentMargin="0" Padding="0" />
                      </ControlTemplate>
                  </Setter.Value>
              </Setter>
          </Style>
      </ListView.ItemContainerStyle>
      <ListView.ItemTemplate>
          <DataTemplate>
          </DataTemplate>
      </ListView.ItemTemplate>
  </ListView>

 

A solution was presented in the second article to programmatically add a single line/row of content for each element in the collection in a StackPanel, dispensing with the ListView. This implementation reduced the line spacing (between lines) to zero. It also demonstrated how to change the XAML code on a page in page Cod Behind, as well as the use of a custom control.

DynamicPanel.Children.Clear(); //DynamicalPanel is a StackPanel on the XAML page
if (ListProperties != null)
{
    foreach (var prop in ListProperties)
    {
        ThreeHoriziontalTextblocks txtValue = new ThreeHoriziontalTextblocks(); //ThreeHorizontalTextBlocks ia a custom control
        val1 = string.Format("{0}", prop.Key);
        val2 =  prop.Value.Item1;
        val3 =  prop.Value.Item2;
        txtValue.SetVal(val1, val2, val3);

        DynamicPanel.Children.Add(txtValue);
    }
}

 

Further enquiries have unearthed the required ListView setting that reduces the spacing in a ListView between items to zero. It involves the MinHeight setting:

<ListView x:Name="ListDeviceProperties" ItemsSource="{Binding ListProperties}" />                      
      <ListView.ItemContainerStyle>
          <Style TargetType="ListViewItem">
              <Setter Property="MinHeight" Value="0"/>
              <Setter Property="Padding" Value="0" />
              <Setter Property="Margin" Value="0" />
              <Setter Property="BorderThickness" Value="0" />
                  <Setter Property="VerticalContentAlignment" Value="Center" />
                  <Setter Property="Template">
                  <Setter.Value>
                      <ControlTemplate TargetType="ListViewItem">
                          <ListViewItemPresenter ContentMargin="0" Padding="0" />
                      </ControlTemplate>
                  </Setter.Value>
              </Setter>
          </Style>
      </ListView.ItemContainerStyle>
      <ListView.ItemTemplate>
          <DataTemplate>
          </DataTemplate>
      </ListView.ItemTemplate>
  </ListView>

 

And the outcome when the app runs is the same as the Codebehind loop technique:

Wala again!