Xamarin Xaml Bind height of button to height of Label - xaml

I got a label and a button next to each other in a grid. I'm trying to get the button to match its Height with the Label.
current XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- vessel label and button -->
<Label StyleClass="headerSub" Grid.Column="0" x:Name="currentVesselLabel"
Text="huidig voertuig:"/>
<Button Grid.Column="1" Text="selecteer voertuig"
BindingContext="{x:Reference currentVesselLabel}"
HeightRequest="{Binding Path=HeightRequest}"
ClassId="selectVesselButton" x:Name="selectVesselButton"/>
</Grid>
I tried setting the BindingContext to the label and bind the HeightRequest property of the button to the Label's Height and HeightRequest property. However, both don't work. How do I bind the height of the button to the height of the Label?

Cause:
It seems that you forgot to set the height of row.When there is only one row in the grid.The default height of row will be set as the height of screen.
Solution:
Set the height of the row.Refer to the following code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- vessel label and button -->
<Label StyleClass="headerSub" Grid.Column="0" x:Name="currentVesselLabel"
Text="huidig voertuig:" VerticalTextAlignment="Center" HeightRequest="60"/>
<Button Grid.Column="1" Text="selecteer voertuig"
BindingContext="{x:Reference currentVesselLabel}"
HeightRequest="{Binding Path=HeightRequest}"
ClassId="selectVesselButton" x:Name="selectVesselButton"/>
</Grid>

Related

ComboBox in a Grid does not fill a grid's cell width

I have a ComboBox in a Grid along with several text boxes.
The Grid is defined like this:
<Grid Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" ColumnSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- All of the text boxes -->
<TextBlock Grid.Column="8" Text="Combo" VerticalAlignment="Center" />
<ComboBox Grid.Column="9" Text="{x:Bind ViewModel.ComboText}" ItemsSource="{x:Bind ViewModel.ComboItems}" HorizontalContentAlignment="Stretch" />
</Grid>
Note that I have added in HorizontalContentAlignment. This has no effect in making the combo fill the Grid, and it still looks like this:
How can I make the ComboBox fill the width of the Cell, equally with the other TextBoxes?
ComboBox in a Grid does not fill a grid's cell width
HorizontalContentAlignment is used to make horizontal alignment of the control's content. If you want to make ComboBox fill a gird cell please set HorizontalAlignment as Stretch.
<ComboBox Grid.Column="9"
Text="{x:Bind ViewModel.ComboText}"
ItemsSource="{x:Bind ViewModel.ComboItems}"
HorizontalAlignment="Stretch" />

How to set height of row in ListView DataTemplate

Question
How can I increase the height of each row in my DataTemplate. I've set the height multiple times in different elements, however the row height doesn't change from the seemingly default height.
What am I missing?
Xaml
<ListView x:Name="ListViewItems">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Tapped="TapGestureRecognizer_Tapped" Height="400">
<Grid Padding="5" Margin="5" HeightRequest="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="400"/>
</Grid.RowDefinitions>
<Label Text="{Binding Title}" Grid.Row="0" Grid.Column="1" FontSize="15"/>
<Image Source="#drawable/cereals.png" Aspect="AspectFill" HeightRequest="400" Grid.Row="0" Grid.Column="0" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Screenshot
If you want to allow a ListView row to set its own height, you need to set the ListView HasUnevenRows property to true.
Just put HasUnevenRows="True"
on the ListView. This should do the trick.

Image flickers in ListView datatemplate

could someone tell me, how can I avoid image flickering in Datatemplate? Everytime I change the source through binding (MVVM pattern), the image in ListViewItem flickers. For other images in app I've used ImageOpened event in code-behind. But I can't be used when I have DataTemplate.
EDIT:
DataTemplate:
<DataTemplate x:Key="ContactItemDataTemplate" x:DataType="contactData:Contact">
<Grid MinHeight="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" x:Name="MainImage" Source="{x:Bind ImageStatusUri, Mode=OneWay}" Margin="0,8,12,8">
</Image>
<TextBlock Grid.Column="1" Text="{x:Bind Nickname, Mode=OneWay}" Foreground="Black" TextAlignment="Center"
VerticalAlignment="Center" FontSize="15" HorizontalAlignment="Left"/>
</Grid>
<Rectangle Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" StrokeThickness="0.4" Height="0.4"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Stroke="#D1D3D4"/>
</Grid>
</DataTemplate>
type Contact implements INotifyPropertyChanged.
EDIT2:
WriteableBitmap is working, but I have 3 images with scaling factors 100, 200 and 400. It always choose the image with scale 400. When I use normal binding no WriteableBitmap, it take image with scale 100.
The best solution here is for you to sub-class the Image control, overriding the Source property and controlling the transition from one image to another with a flicker-less flow. Learn here: https://mva.microsoft.com/en-US/training-courses/xaml-for-windows-10-controls-14482

Force a view to be square in shape

I am trying to create a UI in XAML for Xamarin Forms in which I have a frame (though I assume the answer would be the same for any type of view) inside of a grid. I want the frame to use full width available to it in the grid cell that it occupies, but I want to force it to be square in shape. So, I want the width to size automatically, and have the height set to match its actual width.
Here's what I have so far:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="13*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="1"/>
<Button Grid.Row="1" Grid.Column="1"/>
<Button Grid.Row="2" Grid.Column="1"/>
<Frame Grid.Row="0" Grid.Column="3" Grid.RowSpan="3" OutlineColor="Silver" HorizontalOptions="Fill">
<Image />
</Frame>
</Grid>
Currently, the frame correctly fills the available width, but the height is about the same as the total height of the 3 buttons to the left of it combined.
I was thinking that I maybe needed to bind the frame's HeightRequest to its actual width, but I don't know if that's possible, or how to do it if it is. If not, any other options?
Since you're setting the RowSpan of the frame to 3, even if you explicitly set the frame's HeightRequest to some small value, the frame will still take up the entire grid's height. So first you have to prevent that from happening. You could do that by containing the frame inside some other view.
Now to make the frame's height and width the same as it scales, you could use the container's SizeChanged event and set the frame's height and width requests accordingly.
Also note that Frame by default has a padding of 20.
Here's the sample code for the xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="13*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="1"/>
<Button Grid.Row="1" Grid.Column="1"/>
<Button Grid.Row="2" Grid.Column="1"/>
<StackLayout x:Name="frmContainer" Grid.Row="0" Grid.Column="3" Grid.RowSpan="3" BackgroundColor="Orange">
<Frame x:Name="frm" OutlineColor="Silver" VerticalOptions="Center" HorizontalOptions="Center" Padding="0" BackgroundColor="Green"/>
</StackLayout>
</Grid>
And here's the constructor in the code-behind:
InitializeComponent();
frmContainer.SizeChanged += (s, e) =>
{
frm.HeightRequest = frmContainer.Width;
if (frmContainer.Width > frmContainer.Height)
{
frm.WidthRequest = frmContainer.Height;
}
else
{
frm.WidthRequest = frmContainer.Width;
}
};

How can I design individually the Border-Sides in XAML

How can I design the Border only Top, Left, Right or Bottom Side in XAMl?
In CSS is this possible with Border-Top:...
The border thicknes is a composite property of the left, top, right and bottom thicknesses (notice the difference in order from CSS). If you specify only one value you set all of them, but you can specify them separately:
BorderThickness="1,2,3,4"
In XAML you don't have border property on elements like you have in CSS. However, you can use a <Border> element and set individual thicknesses just as you can i CSS (sets left-right and top-bottom border thickness):
<Border BorderBrush="Blue" BorderThickness="2,4">
<TextBlock Text="Inside border"/>
</Border>
or (sets left, top, right, bottom thickness):
<Border BorderBrush="Blue" BorderThickness="1,2,3,4">
<TextBlock Text="Inside border"/>
</Border>
If you need more control of the border you can use a panel for layout. E.g. using a <Grid>:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" BorderBrush="Blue" BorderThickness="2"/>
<Border Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" BorderBrush="Green" BorderThickness="4"/>
<Border Grid.Row="1" Grid.Column="0" BorderBrush="Red" BorderThickness="3"/>
<Border Grid.Row="1" Grid.Column="2" BorderBrush="Red" BorderThickness="3"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="Inside border"/>
</Grid>
You are free to put other visual elements in the grid cells.