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.
<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?
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 Height
as source property of your binding. Let's do it:
HeightRequest="{Binding Width}"
and this gives the expected 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>
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}}">