Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set a grid column/row size without defining each line?

Tags:

wpf

xaml

I have a grid. I have to define each column and row manually, like this:

<Window x:Class="GridBuild"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="GridBuild" Height="300" Width="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>        
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>        
</Grid>

I want to define the number of rows and columns with a single line, something like this:

<Window x:Class="GridBuild"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="GridBuild" Height="300" Width="300">
    <Grid>
        <Grid.NumberOfRows="2"/>
        <Grid.NumberOfColumns/>
    </Grid>
</Window>
like image 512
Connor Albright Avatar asked May 13 '12 04:05

Connor Albright


People also ask

What does grid-template-rows Auto do?

The grid-auto-rows CSS property is part of the CSS Grid Layout specification, specifying the size of the grid rows that were created without having an explicit size. In other words, this property sets the size of implicit rows and any other rows that have not been explicitly sized in the grid-template-rows property.

How do you span grid items?

Note: The grid-column property is a shorthand property for the grid-column-start and the grid-column-end properties. To place an item, you can refer to line numbers, or use the keyword "span" to define how many columns the item will span.

How do you specify the number of columns in a grid?

To specify the number of columns of the grid and the widths of each column, the CSS property grid-template-columns is used on the grid container. The number of width values determines the number of columns and each width value can be either in pixels( px ) or percentages(%).

How is grid area defined?

A grid area is one or more grid cells that make up a rectangular area on the grid. Grid areas are created when you place an item using line-based placement or when defining areas using named grid areas. Grid areas must be rectangular in nature; it is not possible to create, for example, a T- or L-shaped grid area.


3 Answers

What you describe is called UniformGrid. It has Columns and Rows properties by which you can set the number of rows or columns that you want.

If you don't set these properties, the UniformGrid will try to layout the children as close to a square as it can. In this situation, it prefers to increase the number of columns before increasing the number of rows.

It's an obscure panel, but it's extremely powerful when used correctly.

like image 115
XAMeLi Avatar answered Oct 24 '22 17:10

XAMeLi


I propose deriving from Grid and adding these properties to it like following:

public class GridEx : Grid
{
    public int NumberOfRows
    {
        get { return RowDefinitions.Count; }
        set
        {
            RowDefinitions.Clear();
            for (int i = 0; i < value; i++)
                RowDefinitions.Add(new RowDefinition());
        }
    }

    public int NumberOfColumns
    {
        get { return ColumnDefinitions.Count; }
        set
        {
            ColumnDefinitions.Clear();
            for (int i = 0; i < value; i++)
                ColumnDefinitions.Add(new ColumnDefinition());
        }
    }
}

Now it can be used as following:

<local:GridEx NumberOfRows="3" NumberOfColumns="2">
    <TextBox>some text</TextBox>
    <TextBox Grid.Row="1">some text</TextBox>
    <TextBox Grid.Row="2">some text</TextBox>

    <TextBox Grid.Column="1">some text</TextBox>
    <TextBox Grid.Row="1" Grid.Column="1">some text</TextBox>
    <TextBox Grid.Row="2" Grid.Column="1">some text</TextBox>
</local:GridEx>

Works in designer as well by the way :)

The challenge here is to set different Width, Height etc. for different rows and columns. I have a nice thought how to do this. Also it is possible to automate assigning Grid.Row and Grid.Column. Think of it :)

like image 4
EvAlex Avatar answered Oct 24 '22 17:10

EvAlex


The above answer by EvAlex will work, but only if you don't want to set the number of column/rows using data binding.

public class GridEx : Grid
{
    public int NumberOfRows
    {
        get { return RowDefinitions.Count; }
        set
        {
            RowDefinitions.Clear();
            for (int i = 0; i < value; i++)
                RowDefinitions.Add(new RowDefinition());
        }
    }

    public int NumberOfColumns
    {
        get { return ColumnDefinitions.Count; }
        set
        {
            ColumnDefinitions.Clear();
            for (int i = 0; i < value; i++)
                ColumnDefinitions.Add(new ColumnDefinition());
        }
    }
}

If you do want to set these via data binding (like I do), then with the above solution the compiler will complain because it needs DependencyProperties for that. A DependencyProperty can be implemented (using C# 6's nameof operator) as follows (a quick way to insert it is using the snippet propdp):

public int Columns
{
    get { return (int) GetValue(ColumnsDependencyProperty); }
    set { SetValue(ColumnsDependencyProperty, value); }
}
public static readonly DependencyProperty ColumnsDependencyProperty =
    DependencyProperty.Register(nameof(Columns), typeof(int), typeof(GridEx), new PropertyMetadata(0));

But this way you can't execute the necessary logic to add the necessary number of RowDefinitions. To solve this, define a DependencyPropertyDescriptor for each DependencyProperty and add an AddValueChanged call with the necessary logic to it in your custom class's constructor. The result per propery is then (using C# 6's null-conditional operator ?.):

    public int Columns
    {
        get { return (int) GetValue(ColumnsDependencyProperty); }
        set { SetValue(ColumnsDependencyProperty, value); }
    }
    public static readonly DependencyProperty ColumnsDependencyProperty =
        DependencyProperty.Register(nameof(Columns), typeof(int), typeof(GridEx), new PropertyMetadata(0));

    DependencyPropertyDescriptor ColumnsPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ColumnsDependencyProperty, typeof(GridEx));

    public GridEx()
    {
        ColumnsPropertyDescriptor?.AddValueChanged(this, delegate
        {
            ColumnDefinitions.Clear();
            for (int i = 0; i < Columns; i++)
                ColumnDefinitions.Add(new ColumnDefinition());
        });
    }
like image 3
JvS Avatar answered Oct 24 '22 19:10

JvS