2

There are similar questions to this here and here, but I've tried everything in both of them and they don't fix my problem.

I want to show a grid of checkBoxes on screen in a WPF (layout) grid. These checkboxes have variable length text. I want all the columns to be the same width, and them all to show the text without truncation. That is, I need them all to have the width of the longest text. I want the screen itself to size to content. That is, to be just wide enough to show all the checkboxes.

The list of checkboxes is variable depending on other factors, so I'm using an ItemsControl to show them. A simplified version of the code is below.

If you run this the column with 'Long Text', which is the second column, is much wider than the columns with shorter text. To make them all the same width I've tried using a SharedSizeGroup, and also tried setting MaxWidth = ActualWidth in a column loaded event, which are solutions suggested elsewhere, but these don't work.

I'm sure there must be an easy answer to this, it seems a fairly basic thing to want to do with a layout control. What am I doing wrong please?

XAML:

<Window x:Class="GridColsEqualSize.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight" FontSize="25">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" /> <!-- In the real project second row is for OK/Cancel buttons -->
        </Grid.RowDefinitions>
        <ItemsControl ItemsSource="{Binding CheckBoxItems}"  Grid.Row="0" Grid.Column="0">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <!--Whatever I do I can't get the screen to resize and the cols to have the same width-->
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Text}" IsChecked="{Binding Enabled}"                            
                                  Margin="0,0,10,0"></CheckBox>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Style.Setters>
                        <Setter Property="Grid.Row" Value="{Binding GridRow}" />
                        <Setter Property="Grid.Column" Value="{Binding GridColumn}" />
                    </Style.Setters>
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Grid>
</Window>

C#:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            CheckBoxItems = new List<CheckBoxItem>
            {
                new CheckBoxItem("A", true),
                new CheckBoxItem("B"),
                new CheckBoxItem("C", true),
                new CheckBoxItem("D"),
                new CheckBoxItem("E", true),
                new CheckBoxItem("F"),
                new CheckBoxItem("G"),
                new CheckBoxItem("Long text", true),
                new CheckBoxItem("")

            };
            SetCheckBoxItemRowsAndColumns();
        }

        public List<CheckBoxItem> CheckBoxItems { get; set; }

        private void SetCheckBoxItemRowsAndColumns()
        {
            int currentColumn = 0;
            int currentRow = 0;
            foreach (CheckBoxItem checkBoxItem in CheckBoxItems)
            {
                checkBoxItem.GridColumn = currentColumn;
                checkBoxItem.GridRow = currentRow;
                if (currentColumn != 2)
                {
                    currentColumn++;
                }
                else
                {
                    currentRow++;
                    currentColumn = 0;
                }
            }
        }

        public class CheckBoxItem
        {
            public CheckBoxItem(string text, bool enabled = false)
            {
                Text = text;
                Enabled = enabled;
            }

            public string Text { get; set; }
            public bool Enabled { get; set; }
            public int GridRow { get; set; }
            public int GridColumn { get; set; }
        }

        private void FrameworkContentElement_OnLoaded(object sender, RoutedEventArgs e)
        {
            ((ColumnDefinition)sender).MaxWidth = ((ColumnDefinition)sender).ActualWidth;
        }
    }
Community
  • 1
  • 1
Rich N
  • 8,939
  • 3
  • 26
  • 33
  • 1
    Did you try to use a UniformGrid instead? The UniformGrid arranges a Grid where all cells and rows have the same size. – gomi42 Mar 03 '15 at 10:18
  • Using a UniformGrid would save you the `GridRow` and `GridColumn` view model properties, and would make the `ItemContainerStyle` redundant. The ItemsPanelTemplate would simply be ``. There would also be no need for your `SetCheckBoxItemRowsAndColumns` method. A lot less XAML and code. So I wouldn't agree that SharedSizeScope is "the right solution". – Clemens Mar 03 '15 at 11:32
  • In the actual code (as opposed to the simplified sample here) the checkboxes are in groups. Each group appears in one row, or wraps onto the next row if there are more checkboxes than there are columns in the grid. So the first row could have two checkboxes, the next one six and so on. This is a fairly simple extension of the code above, but I don't think you could do it with a UniformGrid. – Rich N Mar 04 '15 at 18:16

1 Answers1

4

Everything is Ok :) you've choose the right solution 'SharedSizeGroup'

You have only to add Grid.IsSharedSizeScope="True" to your ItemsControl :

    ...
    </Grid.RowDefinitions>
    <ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding CheckBoxItems}"  Grid.Row="0" Grid.Column="0" >
        <ItemsControl.ItemsPanel>
    ...
Yahya
  • 501
  • 4
  • 8