-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Grid row/column definitions styleable #4397
Conversation
917cf94
to
6eaea94
Compare
Can you add unit tests for this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to work well, however there's a definite problem with the way the properties are implemented, and also we need some unit tests that actually test this working with styles. Close though!
CellCache cell = new CellCache(); | ||
|
||
var cell = new CellCache(); | ||
var control = (Control)child; | ||
|
||
// Read indices from the corresponding properties: | ||
// clamp to value < number_of_columns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment isn't really true any more is it? The value's no longer being clamped.
src/Avalonia.Controls/Grid.cs
Outdated
/// </summary> | ||
public ColumnDefinitions ColumnDefinitions | ||
{ | ||
get | ||
{ | ||
if (_data == null) { _data = new ExtendedData(); } | ||
if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; } | ||
if (_data is null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting initialization in the getter for a styled property isn't a good idea because it won't be run when calling e.g. GetValue
or GetObservable
, for example this fails:
[Fact]
public void ColumnDefinitions_Should_Not_Be_Null()
{
var grid = new Grid();
Assert.NotNull(grid.GetValue(Grid.ColumnDefinitionsProperty));
}
It's not really possible to have lazily-initialized styled properties; you should initialize the properties in the constructor. This is the same in WPF/UWP: https://wpf.2000things.com/2010/11/07/118-dont-add-code-to-dependency-property-gettersetter/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@grokys I don't remember about WPF, but UWP has default value factory in the DependencyProperty
See https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.propertymetadata.createdefaultvaluecallback?view=winrt-19041
It also helps in cases, when default value is mutable - https://devblogs.microsoft.com/oldnewthing/20191002-00/?p=102950
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although it doesn't provide access to dependency object itself as I remember
d52dd89
to
9d14e0b
Compare
9389d9f
to
a346964
Compare
Given that this is very out of date by now, and the feature will need changes in the XAML compiler first, I'm going to close this PR to try to reduce noise in our PR list. We should definitely implement this feature though! |
I hate to be that guy, but any updates on this? Is there anything I could help out with? |
If you really need that you can do this workaround using custom control based on Grid (bind to ColumnDefinitionsSource and/or RowDefinitionsSource: public class BindableGrid : Grid
{
public static readonly StyledProperty<string?> ColumnDefinitionsSourceProperty =
AvaloniaProperty.Register<BindableGrid, string?>(nameof(ColumnDefinitionsSource));
public static readonly StyledProperty<string?> RowDefinitionsSourceProperty =
AvaloniaProperty.Register<BindableGrid, string?>(nameof(RowDefinitionsSource));
public BindableGrid()
{
InvalidateDefinitions();
}
public string? ColumnDefinitionsSource
{
get => GetValue(ColumnDefinitionsSourceProperty);
set => SetValue(ColumnDefinitionsSourceProperty, value);
}
public string? RowDefinitionsSource
{
get => GetValue(RowDefinitionsSourceProperty);
set => SetValue(RowDefinitionsSourceProperty, value);
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == ColumnDefinitionsSourceProperty
|| change.Property == RowDefinitionsSourceProperty)
{
InvalidateDefinitions();
}
}
private void InvalidateDefinitions()
{
if (ColumnDefinitionsSource is not null && RowDefinitionsSource is not null)
{
var columns = GridLength.ParseLengths(ColumnDefinitionsSource).Select(x => new ColumnDefinition(x));
ColumnDefinitions.Clear();
ColumnDefinitions.AddRange(columns);
var rows = GridLength.ParseLengths(RowDefinitionsSource).Select(x => new RowDefinition(x));
RowDefinitions.Clear();
RowDefinitions.AddRange(rows);
InvalidateMeasure();
InvalidateArrange();
}
}
} |
@wieslawsoltes Thanks for the workaround, however I am trying to modify the |
@CollinAlpert i would really love to revive this but @grokys and I hasnt settled on a final version of this issue #4464 . until then this will not move forward. Which is quite a shame tbh :( |
I was looking at some things in MAUI which reminded me of this PR and it seems they have a nice solution for this: Their public static readonly BindableProperty ColumnDefinitionsProperty = BindableProperty.Create("ColumnDefinitions",
typeof(ColumnDefinitionCollection), typeof(Grid), null, validateValue: (bindable, value) => value != null,
propertyChanged: UpdateSizeChangedHandlers, defaultValueCreator: bindable =>
{
var colDef = new ColumnDefinitionCollection();
colDef.ItemSizeChanged += ((Grid)bindable).DefinitionsChanged;
return colDef;
}); This is then invoked in |
What does the pull request do?
This is a PR for this concept i had in mind for a long time now. Unit tests seems to pass and ControlCatalog/DataGrid works too.
What is the current behavior?
Currently you can't set Grid's Row/ColumnDefinition property in Styles...
What is the updated/expected behavior with this PR?
This enables the user to set those properties in Styles. If combined with pseudoclasses, it can also enable responsive layout too.
Checklist