Rows Property of UniformGrid

Viewed 57

I am new to WPF and trying to understand how to use a UniformGrid: https://docs.microsoft.com/en-us/windows/communitytoolkit/controls/uniformgrid

If no value for Rows and Columns are provided, the UniformGrid will create a square layout based on the total number of visible items. If a fixed size is provided for Rows and Columns then additional children that can't fit in the number of cells provided won't be displayed.

Based on this text, I thought if I bind a collection of 10 items to a uniform grid and specify 1 row and 3 columns then it would only show 3 items and the other 7 would be cut off.

However, I have built a sample application and with 1 row, 3 columns, and 10 items in my collection, I am getting 4 rows displayed. Here is my sample application:

<Window x:Class="UniformGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UniformGridTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Name="MyMainWindow">
    <ItemsControl ItemsSource="{Binding ActiveList}" Background="Black">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid HorizontalAlignment="Stretch" VerticalAlignment="Center" Rows="1" Columns="3"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding ItemDescription}" Background="Black" Foreground="White"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace UniformGridTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly PlatformSelectorViewModel platformSelectorViewModel = new PlatformSelectorViewModel();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = platformSelectorViewModel;
        }
    }

    public class PlatformSelectorViewModel
    {
        public ObservableCollection<SelectorItem> ActiveList { get; }

        public PlatformSelectorViewModel()
        {
            ActiveList = new ObservableCollection<SelectorItem>();
            ActiveList.Add(new SelectorItem() { ItemDescription = "Super Nintendo Entertainment System" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Nintendo Entertainment System" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Sega Genesis" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Sega CD" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Turbo Grafx 16" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Nintendo Gamecube" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Nintendo Wii" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Sony Playstation" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Nintendo PSP" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Nintendo Playstation 2" });
            ActiveList.Add(new SelectorItem() { ItemDescription = "Arcade" });
        }
    }

    public class SelectorItem : INotifyPropertyChanged
    {
        private string itemDescription;
        public string ItemDescription
        {
            get { return itemDescription; }
            set
            {
                itemDescription = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ItemDescription"));
            }
        }

        private bool isSelected;
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }
}

Result: A uniform grid with 3 rows and 4 columns displaying 11 items (the last cell is empty).

Based on the documentation on UniformGrid, I had expected that I would get 1 row with 3 items uniformly laid out and the other 7 items would not display. Did I misunderstand the documentation or am I doing something incorrectly that is causing additional rows to display?

1 Answers

First of all, you are refering to the wrong documentation, yours is for UWP, not WPF.

The behavior should be the same, but it is not explicitly stated in the referenced documentation for WPF. However, there seems to be an issue that stems from setting VerticalAlignment to Center and is not related to the ItemsControl, it will be the same for an isolated UniformGrid.

Whenever the UniformGrid contains more than the maximum number of items it can display (Rows x Columns) and the VerticalAlignment is set to any other value than the default Stretch, all of the items are displayed regardless of the number of rows, but respecting the number of columns.

What you could do is remove the VerticalAlignment and try to compensate for it by aligning the ItemsControl in a way that it fits your original intent.

<ItemsPanelTemplate>
   <UniformGrid HorizontalAlignment="Stretch" Rows="1" Columns="3"/>
</ItemsPanelTemplate>
Related