nor0x
nor0x

Reputation: 1213

Xamarin.Forms bind Height of Grid to Width of Button

I try to build the following UI Element with Xamarin.Forms. I was able to build this with UWP by binding the Height property of the TopGrid to the ActualWidth property of Button1. However this is not working in Xamarin.Forms, because there is no ActualWidth property. I already tried binding the Height of TopGrid to WidthRequest, but without success.

enter image description here

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid x:Name="TopGrid" Grid.Row="0" BindingContext="{x:Reference Name=Button1}"  Height="{Binding Path=WidthRequest}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button x:Name="Button1" Grid.Column="0" Text="1" />
        <Button x:Name="Button2" Grid.Column="1" Text="2" />
        <Button x:Name="Button3" Grid.Column="2" Text="3" />
        <Button x:Name="Button4" Grid.Column="3" Text="4" />
    </Grid>
</Grid>

Does anybody have experience with Xamarin.Forms and can help me with this problem?

Upvotes: 4

Views: 13092

Answers (2)

Stephane Delcroix
Stephane Delcroix

Reputation: 16232

First thing first: Xaml names are case-sensitive, so instead of

BindingContext="{x:Reference Name=button1}"

this should be

BindingContext="{x:Reference Name=Button1}"

Beside this, your Xaml was almost ok. Let's look at

Height="{Binding Path=WidthRequest}"

You're trying to bind to the view's height, but the HeightProperty is a read-only BindableProperty, so you can't set it. If you look at the API, there's no public setter for the Height property either. So, instead of binding to the Height, you should bind to the HeightRequest.

HeightRequest="{Binding Path=WidthRequest}"

That's the way of saying that you'd like the Grid to be of that height, and the layout system will do its best to make you happy (but that's a best effort only).

I think you get this by now. The button WidthRequest is the request made by the user, and in this case, it's not set and it's value is left to the default. Instead, you want to use the button's actual Width as source property of your binding. Let's do it:

HeightRequest="{Binding Width}"

and this gives the expected result:

actual result

Here's the full corrected Xaml snippet:

<Grid>
  <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid x:Name="TopGrid" Grid.Row="0" BindingContext="{x:Reference Name=Button1}"  HeightRequest="{Binding Width}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Button x:Name="Button1" Grid.Column="0" Text="1" BackgroundColor="Pink"/>
    <Button x:Name="Button2" Grid.Column="1" Text="2" BackgroundColor="Pink"/>
    <Button x:Name="Button3" Grid.Column="2" Text="3" BackgroundColor="Pink"/>
    <Button x:Name="Button4" Grid.Column="3" Text="4" BackgroundColor="Pink"/>
  </Grid>
</Grid>

Upvotes: 13

Martin Rhodes
Martin Rhodes

Reputation: 1118

If you don't want to set the BindingContext for the whole grid (and every item in it), then you can just specify it directly in the binding as follows, allowing all other controls to retain their original BindingContext:

 <Grid x:Name="TopGrid" Grid.Row="0" HeightRequest="{Binding Width, Source={x:Reference Button1}}">

Upvotes: 4

Related Questions