You can't do that. As you said, the GridLength is a struct, but maybe more important than that is that the Value that you are setting is simply a public property with a getter (it's not even a BindableProperty). This means that you can only set it via a method, which in this case happens to be the GridLength ctor itself. You can check the code of the GridLength here.
What you can do is one of 2 things - either leave all of the widths that you need to be Auto, or subclass the Grid class.
If you decide to go for the first approach, you won't have to write any additional code. According to the Rows and columns docs:
Auto – the row height or column width is autosized based on the cell contents (Auto in XAML).
On a first glance, this should do the work, since all widths will take the max of the children's widths (in this case it will be 150). Unfortunately, this adds some overhead to the Grid's rendering and it is not small at any case. If you look a bit down in the docs, you will see in a red warning, that you should:
Try to ensure that as few rows and columns as possible are set to Auto size. Each auto-sized row or column will cause the layout engine to perform additional layout calculations. Instead, use fixed size rows and columns if possible. Alternatively, set rows and columns to occupy a proportional amount of space with the GridUnitType.Star enumeration value.
This can also be seen again in Optimize layout performance, which I strongly suggest you to read, if you have not already.
That being said, you can go with the second approach. The idea behind it is to have a bindable property inside your new class and upon setting this property, you will update your ColumnDefinition's Width property. Unfortunately, this has to be done "manually". Here is an example with your property (I have changed its type to double to be the same as the column's Width property):
public partial class MainPage
{
private ColumnDefinition column3;
public static readonly BindableProperty EntryWidthProperty = BindableProperty.Create(nameof(EntryWidth), typeof(double),
typeof(SingleEntryGrid), (double) 150, BindingMode.TwoWay);
public double EntryWidth
{
get => (double) GetValue(EntryWidthProperty);
set
{
SetValue(EntryWidthProperty, value);
if (column3 != null)
{
column3.Width = value;
}
}
}
public MainPage()
{
InitializeComponent();
var grid = new SingleEntryGrid
{
ColumnDefinitions = new ColumnDefinitionCollection()
};
// TODO: Other columns
column3 = new ColumnDefinition
{
// The default value for EntryWidth
Width = new GridLength(150, GridUnitType.Absolute)
};
grid.ColumnDefinitions.Add(column3);
// The rest of your code
Content = grid;
}
}
As you can see in the code, the third column is being set initially to an Absolute width of 150 (the default value for your EntryWidth). After some change in the EntryWidth property's value, the setter will automatically change the third column.
Of course, this isn't the most elegant solution, since it is always updating only the third column, but you can continue from here. Since I don't know exactly what is the case and what it will be used against, I can't say what is the best choice - either create more properties for each column, or create a list of them with a key-value (may even be a separate class) bound to them - that way you can have it dynamically set for each column.
P.S. And still, if you know your widths from the start, or you have only 1 column that needs to be Auto, go with the traditional approach. Try not to overcomplicate everything and set your column definitions accordingly.
Edit: According to the updated question, we should take another approach. From the image I can't fully understand what the overall template is, but we have 2 options here:
- To have all of the inputs to be the same width everywhere;
- Or to have different widths.
However, whatever we choose, the column will have the same width for all views. What I can suggest in this case is to have all of the inputs be the same width as well (set their HorizontalOptions to StartAndExpand or FillAndExpand). And instead of setting their width explicitly, you can try to set the column's width to be (depending on your other columns' configuration):
- If you don't have other columns set to
Star (*) or you don't want the column to be proportionate to the other stars - set its width to Star. This way the column will take whatever it has remaining.
- Or set the columns' width to be an
Absolute value.
You shouldn't try to change the column dynamically - it won't be a good UX and you will also have to add checks when to stop.
To sum up, either set the third column (containing the entries) to Star, or to Absolute. If one of your other columns is set to Auto and the other has an Absolute width, you can easily set the third one to Star, which will take as much width as it has left). An Absolute should be used if you want to take "that much" of the width every time (use it with the largest entry/symbols that you want visible).