c# - Fill all horizontal space with Border - Stack Overflow

admin2025-04-25  2

I have a collection of objects inside Grid. Each object is displayed within a Border. What I need is to each Border - tile to take all available horizontal space. Right now I have a set of rectangles of various shapes and sizes which doesn't look really good.

This is content definition:

Content = new AbsoluteLayout
{
    Children =
    {
        new ScrollView
        {
            Content = new Grid
            {
                Children =
                {
                    collectionView
                        .Bind(ItemsView.ItemsSourceProperty, nameof(_viewModel.Notifications))
                }
            }
        },
        buttonCorner.Text("New")
        .LayoutBounds(1, 1, -1, -1).LayoutFlags(AbsoluteLayoutFlags.PositionProportional)
    }
}.BackgroundColor(Colors.Snow).Margin(20);

This is definition of the CollectionView

var collectionView = new CollectionView();
collectionView.ItemTemplate = new DataTemplate(() =>
{
    var border = new Border
    {
        Stroke = Colors.LightGray,
        StrokeThickness = 1,
        StrokeShape = new RoundRectangle { CornerRadius = 10 },
        BackgroundColor = Colors.White//,
        //HorizontalOptions = LayoutOptions.FillAndExpand //deprecated, doesn't do anything
    };
    var grid = new Grid
    {
        Padding = 10,
        RowDefinitions = new RowDefinitionCollection
        {
            new RowDefinition(GridLength.Auto),
            new RowDefinition(GridLength.Auto)
        },
        ColumnDefinitions = new ColumnDefinitionCollection
        {
            new ColumnDefinition(GridLength.Auto),
            new ColumnDefinition(GridLength.Auto)
        }
    };

    var titleLabel = new Label
    {
        FontAttributes = FontAttributes.Bold,
        FontSize = 18,
        TextColor = Colors.Black
    };
    titleLabel.SetBinding(Label.TextProperty, "Title");
    var descriptionLabel = new Label
    {
        FontSize = 14,
        TextColor = Colors.Gray
    };
    descriptionLabel.SetBinding(Label.TextProperty, "Description");
    var buttonDelete = new Button
    {
        Text = "Delete",
        BackgroundColor = Colors.Red,
        TextColor = Colors.White,
        Padding = 5,
        FontSize = 12,
    };
    buttonDelete.Clicked += async (sender, e) =>
    {
        if (sender is Button btn && btn.BindingContext is Notification notification)
        {
            await _viewModel.Delete(notification.Id);
            await _viewModel.Initialize();
        }
    };
    buttonDelete.SetBinding(BindableObject.BindingContextProperty, ".");

    grid.Add(titleLabel, 0, 0);
    grid.Add(descriptionLabel, 0, 1);
    grid.Add(buttonDelete, 1, 0);
    border.Content = grid;

    return border;
});
collectionView.ItemsLayout = new GridItemsLayout(1, ItemsLayoutOrientation.Vertical)
{
    Span = 1 //doesn't do anything
};

I'm out of ideas. Everything either does nothing or triggers errors/warnings. LayoutOptions.Fill doesn't do anything either.

If no one here knows how to fix it, I will have to switch to XAML markup, C# markup lacks necessary documentation.

I have a collection of objects inside Grid. Each object is displayed within a Border. What I need is to each Border - tile to take all available horizontal space. Right now I have a set of rectangles of various shapes and sizes which doesn't look really good.

This is content definition:

Content = new AbsoluteLayout
{
    Children =
    {
        new ScrollView
        {
            Content = new Grid
            {
                Children =
                {
                    collectionView
                        .Bind(ItemsView.ItemsSourceProperty, nameof(_viewModel.Notifications))
                }
            }
        },
        buttonCorner.Text("New")
        .LayoutBounds(1, 1, -1, -1).LayoutFlags(AbsoluteLayoutFlags.PositionProportional)
    }
}.BackgroundColor(Colors.Snow).Margin(20);

This is definition of the CollectionView

var collectionView = new CollectionView();
collectionView.ItemTemplate = new DataTemplate(() =>
{
    var border = new Border
    {
        Stroke = Colors.LightGray,
        StrokeThickness = 1,
        StrokeShape = new RoundRectangle { CornerRadius = 10 },
        BackgroundColor = Colors.White//,
        //HorizontalOptions = LayoutOptions.FillAndExpand //deprecated, doesn't do anything
    };
    var grid = new Grid
    {
        Padding = 10,
        RowDefinitions = new RowDefinitionCollection
        {
            new RowDefinition(GridLength.Auto),
            new RowDefinition(GridLength.Auto)
        },
        ColumnDefinitions = new ColumnDefinitionCollection
        {
            new ColumnDefinition(GridLength.Auto),
            new ColumnDefinition(GridLength.Auto)
        }
    };

    var titleLabel = new Label
    {
        FontAttributes = FontAttributes.Bold,
        FontSize = 18,
        TextColor = Colors.Black
    };
    titleLabel.SetBinding(Label.TextProperty, "Title");
    var descriptionLabel = new Label
    {
        FontSize = 14,
        TextColor = Colors.Gray
    };
    descriptionLabel.SetBinding(Label.TextProperty, "Description");
    var buttonDelete = new Button
    {
        Text = "Delete",
        BackgroundColor = Colors.Red,
        TextColor = Colors.White,
        Padding = 5,
        FontSize = 12,
    };
    buttonDelete.Clicked += async (sender, e) =>
    {
        if (sender is Button btn && btn.BindingContext is Notification notification)
        {
            await _viewModel.Delete(notification.Id);
            await _viewModel.Initialize();
        }
    };
    buttonDelete.SetBinding(BindableObject.BindingContextProperty, ".");

    grid.Add(titleLabel, 0, 0);
    grid.Add(descriptionLabel, 0, 1);
    grid.Add(buttonDelete, 1, 0);
    border.Content = grid;

    return border;
});
collectionView.ItemsLayout = new GridItemsLayout(1, ItemsLayoutOrientation.Vertical)
{
    Span = 1 //doesn't do anything
};

I'm out of ideas. Everything either does nothing or triggers errors/warnings. LayoutOptions.Fill doesn't do anything either.

If no one here knows how to fix it, I will have to switch to XAML markup, C# markup lacks necessary documentation.

Share Improve this question asked Jan 16 at 13:18 Aveyron2033Aveyron2033 234 bronze badges 5
  • Don't bother with AbsoluteLayout. If your parent object is a Grid, then, the Border elements can be instantiated directly as children with WidthRequest/HeightRequest/TranslationX/TranslationY set respectively. – Stephen Quan Commented Jan 16 at 14:21
  • @StephenQuan I have removed AbsoluteLayout and indeed it was the problem, but now I need to figure out how to anchor the button to the corner. Usually it would be done with AbsoluteLayout. – Aveyron2033 Commented Jan 16 at 14:54
  • You can set HorizontalOptions and VerticalOptions to anchor to a different corner. – Stephen Quan Commented Jan 16 at 15:08
  • @StephenQuan I don't know if it's correct solution, but applying .End() and .Bottom() to the button forces it to bottom right corner, which works for me. – Aveyron2033 Commented Jan 16 at 18:11
  • @Averyron2033 yup End() and Bottom() are View extensions for setting HorizontalOptions and VerticalOptions. – Stephen Quan Commented Jan 17 at 9:31
Add a comment  | 

1 Answer 1

Reset to default 1

The outer ScrollView is placed inside the AbsoluteLayout but you don't set the size limit of the ScrollView. If you set the HorizontalOption of Border which is inside the ScrollView to LayoutOptions.Fill, it may not know how much space it should take.

You may try defining the size of ScrollView in the AbsoluteLayout since it is the child element of AbsoluteLayout, e.g.

    new ScrollView
    {
        Content = new Grid
        {
            Children =
            {
                collectionView
                    .Bind(ItemsView.ItemsSourceProperty, nameof(_viewModel.Notifications))
            }
        }
    }.LayoutBounds(-1, -1, 1, 1).LayoutFlags(AbsoluteLayoutFlags.SizeProportional)

The above code use proportional values to define the size of ScrollView to fill the whole space. Then the Border should fill all Horizontal space when using LayoutOptions.Fill. For more info about AbsoluteLayoutFlags, please refer to Proportional positioning and sizing

Please let me know if you have any question.

转载请注明原文地址:http://anycun.com/QandA/1745530402a90828.html