Can you define RowDefinition in style xamarin forms - xamarin.forms

I have the following
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="1.5*"></RowDefinition>
<RowDefinition Height="7.5*"></RowDefinition>
</Grid.RowDefinitions>
and I would like to define the Height in a Style or in a variable in the app.xaml.
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource myHeight}"></RowDefinition>
<RowDefinition Height="{StaticResource myHeight2}"></RowDefinition>
</Grid.RowDefinitions>
Is this possible? I have tried but I get an error.
The reason I want to achieve this is that on small devices I need to change the row height.
I would appreciate any tips or suggestions.

You can bind a model to ContentPage , then Grid can use binded data by model and row height can be setted by model data (contain row height paramaters).
For example , create a sample ViewModel(RowHeightClass) as follow :
using Xamarin.Essentials;
public class RowHeightClass
{
public GridLength rowFirstHeight { set; get; }
public GridLength rowSecondHeight { set; get; }
public RowHeightClass()
{
// here can add code set by device screen
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
double screenheight = mainDisplayInfo.Height;
rowFirstHeight = new GridLength(DeviceDisplay * 0.2);
rowSecondHeight = new GridLength(DeviceDisplay * 0.4);
}
}
Binding it in ContentPage :
RowHeightClass rowHeightClass = new RowHeightClass();
BindingContext = rowHeightClass;
Used in XAML :
<Grid VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="{Binding rowFirstHeight}" />
<RowDefinition Height="{Binding rowSecondHeight}" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Grid.Row="0"
Grid.Column="0"
BackgroundColor="Blue" />
<BoxView Grid.Row="1"
Grid.Column="0"
BackgroundColor="Red" />
<Button Grid.Row="2"
Grid.Column="0"
BackgroundColor="Yellow"
Clicked="Button_Clicked" />
</Grid>
Note : You can modify the constructor method of RowHeightClass to add method to set needed height by the size of device screen .
==================================Update=====================================
Using StaticResource also can set the heigh of row . Add a Resources for Grid or Application as follow :
<Grid VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.Resources>
<ResourceDictionary>
<x:Double x:Key="SmallScreenRowheight">200</x:Double>
<x:Double x:Key="LargeScreenRowheight">400</x:Double>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource SmallScreenRowheight}" />
<RowDefinition Height="{StaticResource LargeScreenRowheight}" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Grid.Row="0"
Grid.Column="0"
BackgroundColor="Blue" />
<BoxView Grid.Row="1"
Grid.Column="0"
BackgroundColor="Red" />
<Button Grid.Row="2"
Grid.Column="0"
BackgroundColor="Yellow"
Clicked="Button_Clicked" />
</Grid>

Related

Load ContentView inside CarouselView in Xamarn forms

I am trying to create a scrollable tabs in Xamarin.Forms with CollectionView and CarouselView as specified in this link. I need to load different ContentView in CarouselView based on the Tab selected in the header.
I tried like below but the ContentView is not displaying..
Below is xaml Code:
<Grid x:DataType="{x:Null}" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CollectionView
x:Name="CustomTabsView"
Grid.Row="1"
HorizontalScrollBarVisibility="Never"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding TabVms}"
ItemsUpdatingScrollMode="KeepItemsInView"
SelectedItem="{Binding CurrentTabVm, Mode=TwoWay}"
SelectionMode="Single"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3" />
</Grid.RowDefinitions>
<Label
x:Name="TitleLabel"
Grid.Row="0"
Padding="15,0"
FontAttributes="Bold"
FontSize="Small"
HeightRequest="50"
HorizontalTextAlignment="Center"
Text="{Binding Title}"
TextColor="White"
VerticalTextAlignment="Center" />
<BoxView
x:Name="ActiveIndicator"
Grid.Row="1"
BackgroundColor="Red"
IsVisible="{Binding IsSelected, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<ContentView
x:Name="dynamiccontent"
BackgroundColor="White"
Content="{Binding DynamicContentView, Mode=TwoWay}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
.cs file Code
private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
var x = e.CurrentItem as TabItem;
var viewModel = BindingContext as xxxViewModel;
if(x.Header == Tab1)
{
viewModel.TabVms[0].DynamicContentView = new Page1();
}
if(x.Header == Tab2)
{
viewModel.TabVms[1].DynamicContentView = new Page2();
}
}
Any help is appreciated!
You could use DataTemplateSelector.
Creating a DataTemplateSelector:
class DymaicDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Tab1Template { get; set; }
public DataTemplate Tab2Template { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((TabViewModel)item).Header == "Tab1" ? Tab1Template : Tab2Template;
}
}
Consuming a DataTemplateSelector in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="tab1Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Red"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="tab2Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Green"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<local:DymaicDataTemplateSelector
x:Key="dymaicDataTemplateSelector"
Tab1Template="{StaticResource tab1Template}"
Tab2Template="{StaticResource tab2Template}" />
</ResourceDictionary>
</ContentPage.Resources>
Assign it to the ItemTemplate property:
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource dymaicDataTemplateSelector}"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never" />

UWP - automationProperties.Name in case of a change in value

I have a ListView which is populating the result based on DataTemplate. See the code below
I am raising property changed event in cpp to reflect the same in UI for ResultText field.
But the same value is not getting reflected in AutomationProperties.Name.
How to update AutomationProperties.Name ?
<DataTemplate x:DataType="local:testResults">
<Grid x:Name="diagGrid" HorizontalAlignment="Stretch" Visibility="{x:Bind ShowStage, Mode=OneWay}" AutomationProperties.Name="{x:Bind ResultText}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind ResultSymbol, Mode=OneWay}" Foreground="{x:Bind SymbolColor, Mode=OneWay}" Visibility="{x:Bind IsStageComplete, Mode=OneWay}" HorizontalAlignment="Center"/>
<ProgressRing Grid.Column="0" IsActive="{x:Bind IsStageRunning, Mode=OneWay}" Margin="10,0,20,0" HorizontalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{x:Bind StageName, Mode=OneWay}" Foreground="{ThemeResource AppBarItemDisabledForegroundThemeBrush}">
</TextBlock>
<TextBlock x:Name="test" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Text="{x:Bind ResultText, Mode=OneWay}" Margin="10" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>```
I added mode=OneWay, then it worked.
AutomationProperties.Name="{x:Bind ResultText, Mode=OneWay}">

Frame not taking the full height Xamarin forms

I have Xamarin page which has a grid with two rows and a column. In the first row/column I have a label and the second row/column I have a frame where it does not take the full height of the row. Could you help, please?
<controls:GradientColorStack
StartColor="#0cacee"
EndColor="#0574d8"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
GradientOreintation="Vertical">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="330" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
Grid.Row="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Text="" />
<controls:CustomFrame
Grid.Row="1"
CornerRadius="30,30,0,0"
BackgroundColor="White"
HasShadow="True"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="12,20,12,0" />
</Grid>
</controls:GradientColorStack>
There is default spacing in Row and Column .
Grid has properties to control spacing between rows and columns. The following properties are available for customizing the Grid:
ColumnSpacing – the amount of space between columns. The default value of this property is 6.
RowSpacing – the amount of space between rows. The default value of this property is 6.
Here you can set RowSpacing= "0" to get full height of the row.
<Grid BackgroundColor="Accent" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="330"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label BackgroundColor="Wheat" Grid.Column="0"
Grid.Row="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Text="1111111111" />
<Frame
Grid.Row="1"
BackgroundColor="White"
HasShadow="True"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="12,0,12,0" />
</Grid>
By the way Margin="12,20,12,0" also can affect the top space, if not necessary ,can set this : Margin="12,0,12,0"
Works fine with frames ?
<Frame
BackgroundColor="Red"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="370" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
BackgroundColor="GREEN"
Grid.Row="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="Start"
Text="LOL" />
<Frame
Grid.Row="1"
Grid.Column="0"
BackgroundColor="White"
HasShadow="True"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="12,20,12,0">
<StackLayout>
<Label Text="Text" />
</StackLayout>
</Frame>
</Grid>
</Frame>

Change grid layout at runtime

I have a grid with the following row definitions...
<Grid.RowDefinitions>
<RowDefinition Height="5*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
When the user presses a button, how do I remove the bottom two rows and have the top row (including the view within it) stretch to the bottom of the grid?
I kept all the rows and did this...
mainGrid.RowDefinitions[2].Height = new GridLength(1, GridUnitType.Star);
mainGrid.ForceLayout();
I would like to animate the change in height.
Try something like this:
The grid
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="5*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
x:Name="stkOne"
BackgroundColor="Red"/>
<StackLayout Grid.Row="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
x:Name="stkTwo"
BackgroundColor="Green"/>
<StackLayout Grid.Row="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
x:Name="stkThree"
BackgroundColor="Blue"/>
<Button Text="Expand One"
HorizontalOptions="EndAndExpand"
Command="ExpandCommand"/>
</Grid>
The code behind
// Create the command and set it up to execute this method:
void ExecuteExpand()
{
stkTwo.IsVisible=false;
stkThree.IsVisible=false;
Grid.SetRowSpan(stkOne, 3);
grid.ForceLayout();
}
I'm not sure if it will work as you need, but make a try.

How to setup Row/Column Definitions in Xamarin.Forms Xaml?

I managed to setup rows and columns from the code but couldn't move this settings to xaml:
grid.RowDefinitions = new RowDefinitionCollection {
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }
};
grid.ColumnDefinitions = new ColumnDefinitionCollection {
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
};
The following doesn't work:
<Grid x:Name="grid" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
...
</Grid>
From the documentation I managed to fetch only c# implementation
I also get the same behaviour (does not fill and expand) for a grid with a single cell (1 row / column, although I am not sure why we would ever need a grid with a single cell full size of screen), but it seems to work fine for a 2 x 2, 3 x 3 cell grid (have not tried others yet).
The Height="" and Width="" attributes are required in Xamarin Forms although I "think" they are not needed in WPF as the default assumes this is the case.
<ContentPage.Content>
<Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Text="1"></Button>
<Button Grid.Row="1" Grid.Column="1" Text="2"></Button>
</Grid>
</ContentPage.Content>
Here is a sample
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Top Left" Grid.Row="0" Grid.Column="0" />
<Label Text="Top Right" Grid.Row="0" Grid.Column="1" />
<Label Text="Bottom Left" Grid.Row="1" Grid.Column="0" />
<Label Text="Bottom Right" Grid.Row="1" Grid.Column="1" />
</Grid>

Resources