Understanding WidthRequest

21,610

Solution 1

WidthRequest just describes an element's desired width during the next layout cycle.
For it to work as you'd expect, 2 conditions must be satisfied:
1) the requested width is consistent with all constraits (ex. parent's width) and
2) a layout cycle is triggered.
WidthRequest: https://developer.xamarin.com/api/property/Xamarin.Forms.VisualElement.WidthRequest/

But that's complicated. I'd recommend just replacing the stack layout with a grid, and putting each element in a column of the desired width.
Grid Example: https://developer.xamarin.com/api/type/Xamarin.Forms.Grid/

Solution 2

You need to specify a HorizontalOptions such as "start" or "center". The default horizontalOptions for stackLayout is FillAndExpand, so child elements like a listview will fill the entire available horizontal area even though you specify a width. This was a bad call on behalf of Microsoft because the default behavior will ignore/override a width request.

Here is a visual example: I have a picker where I set the width request to 200, which should take up about 2/3 of the horizontal space.

<StackLayout Padding="10">
    <Picker x:Name="pickerRanks" WidthRequest="200" />
</StackLayout>

Width request ignored

As you can see the width request is overridden/ignored. Then if after setting the HorizontalOptions to "Start"...

<StackLayout Padding="10">
    <Picker x:Name="pickerRanks" WidthRequest="200" HorizontalOptions="Start"/>
</StackLayout>

Width request honored

The width request is honored. Of course I'm setting the properties in the .xaml file here, which I usually prefer but you can also set the HorizontalOptions in C# like this

pickerRanks.HorizontalOptions = LayoutOptions.Start;
Share:
21,610
testing
Author by

testing

Updated on July 09, 2022

Comments

  • testing
    testing almost 2 years

    I want to change the WidthRequest. Thereby I noticed that this doesn't really set the width of an element. Rather it is kind of a proposal.

    Example: I have a ListView added as child to a StackLayout. I'm setting a WidthRequest for the ListView, but the result is not what I expect.

    this.listView = new ListView
    {
        ItemsSource = new List<IconMenu>
        {
            // creation of some entries
            // ...
        },
        ItemTemplate = new DataTemplate(typeof(IconMenuCell)),
        RowHeight = 44,
        // HERE is the problematic code!
        WidthRequest = 10,
    };
    
    Content = new StackLayout
    {
        Orientation = StackOrientation.Horizontal,
        Children = {
            this.listView,
            this.detailView,
        },
    };
    

    This is the structure/layout of IconMenuCell:

    public IconMenuCell()
    {
        var icon = new Image
        {
            Aspect = Aspect.AspectFit,
            WidthRequest = 40,
        };
        icon.SetBinding(Image.SourceProperty, "IconSource");
    
        this.textLabel = new Label {
            TextColor = Color.Gray,
            FontSize = 10,
            VerticalOptions = LayoutOptions.Center,
        };
        this.textLabel.SetBinding(Label.TextProperty, "Text");
    
        View = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            Children =
            {
                icon,
                this.textLabel,
            },
        };
    }
    

    Setting the WidthRequest to 10 doesn't make sense, because the icon itself should take 40. But here I get the smallest width for the whole list view.

    There is no difference if I set WidthRequest to 60 or 120. The resulting width is the same (and not what I want).

    How does WidthRequest work here? Do I have to change some LayoutOptions?