Can you please recommend me some sample code to create framed lines as shown in the picture. As you can see in the image, for example for the first row, M should be in one f
First of all, grid column indices start at '0'(i.e., if u have 4 columns, their indices will be [0,1,2,3]).
Back to the question:
Your approach seems very strange: you put 4 elements in 4 grid cells 'independently', but 3 of this elements have to be placed within common border. You may try to put this 3 elements in another container(for example, in stack layout), and then add a border to this container. Frame class itself is very poor, but here is some workaround using custom renderers.
Thus, listview cell may look like this:
<StackLayout Orientation="Horizontal">
<local:FrameWithBorder>
<Label Text="{Binding DisplayName}" />
</local:FrameWithBorder>
<local:FrameWithBorder HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Type}" />
<Label Text="{Binding CreationDate}" />
<Label Text="{Binding CompletionDateInfo}" />
</StackLayout>
</local:FrameWithBorder>
</StackLayout>
PS> I'm not much experienced in Xamarin, so, any suggestions and corrections would be greatly appreciated.
EDIT: do not put listview inside scrollview
Thanks for your answers but this is I have implemented it, I mostly used Grid control, I am sharing it here in case you need a similar screen:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XYZclass.Views.Exams.ExamsPage"
BackgroundColor="White"
xmlns:controls="clr-namespace:XYZclass.Controls">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 10"
Android="0,0,0,10"/>
</ContentPage.Padding>
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="TextColor" Value="White"/>
<Setter Property="Font" Value="Medium"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
</Style>
<Style x:Key="LabelStyleSmall" TargetType="Label">
<Setter Property="TextColor" Value="#41a4dc"/>
<Setter Property="Font" Value="Small"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<controls:Navigation/>
</Grid>
<Grid RowSpacing="0" Grid.Row="1" Padding="10,10,10,0">
<Grid.RowDefinitions>
<RowDefinition Height="145*" />
<RowDefinition Height="415*" />
<RowDefinition Height="2*" />
<RowDefinition Height="88*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" RowSpacing="10" BackgroundColor="#ed004a">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="#ed004a" Padding="30,0,0,0">
<Label Text="Your personal exam history information"
Style="{StaticResource LabelStyle}"
HorizontalOptions="StartAndExpand"/>
</Grid>
<Grid Grid.Row="1"
BackgroundColor="#0075c1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text=""
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
Text="Type:"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="2"
Text="Created:"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="3"
Text="Finished:"
Style="{StaticResource LabelStyle}"/>
</Grid>
</Grid>
<ScrollView Grid.Row="1">
<ListView x:Name="ExamList"
ItemsSource="{Binding Exams}"
HorizontalOptions="Center"
RowHeight="70">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<Frame OutlineColor="#ed004a" Grid.Column="0">
<Frame.Content>
<Label Text="{Binding Name}"
Font="Large"
Style="{StaticResource LabelStyle}"
TextColor="#ed004a"
FontAttributes="Bold"/>
</Frame.Content>
</Frame>
<Frame OutlineColor="#ed004a" Grid.Column="1">
<Frame.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="{Binding Type}"
Style="{StaticResource LabelStyleSmall}"/>
<Label Grid.Column="1"
Text="{Binding StartDateText}"
Style="{StaticResource LabelStyleSmall}"/>
<Label Grid.Column="2"
Text="{Binding FinishedDateText}"
Style="{StaticResource LabelStyleSmall}"/>
</Grid>
</Frame.Content>
</Frame>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
<BoxView Grid.Row="2" Color="#0075c1" WidthRequest="100" HeightRequest="2"/>
<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="40*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"
BackgroundColor="{Binding DeleteButtonBackgroundColor}"
Padding="30,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
x:Name="LabelDeleteSelectedExamsPartOne"
Text="{Binding DeleteButtonText}"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
x:Name="LabelDeleteSelectedExamsPartTwo"
Text=""
Style="{StaticResource LabelStyle}"
Font="Large"/>
<Grid.GestureRecognizers IsEnabled="{Binding DeleteButtonIsEnabled}">
<TapGestureRecognizer
Command="{Binding DeleteSelectedExamsCommand}"/>
</Grid.GestureRecognizers>
</Grid>
<Grid Grid.Column="2"
BackgroundColor="#0075c1"
Padding="30,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
x:Name="LabelCreateNewExamPartOne"
Text="Create New Exam "
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
x:Name="LabelCreateNewExamPartTwo"
Text=""
Style="{StaticResource LabelStyle}"
Font="Large"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding CreateNewExamCommand}"/>
</Grid.GestureRecognizers>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</ContentPage>
Please ignore my previous answer, this is a much better answer to my own question: I have improved my code and now I create the items dynamically in the code behind, please use the following code if you need a similar screen:
Please see that I am creating "GridExams" dynamically in the code behind:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XYZProject.Views.Exams.ExamsPage"
BackgroundColor="White"
xmlns:controls="clr-namespace:XYZProject.Controls">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 10"
Android="0,0,0,0"/>
</ContentPage.Padding>
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="TextColor" Value="White"/>
<Setter Property="Font" Value="Medium"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
</Style>
<Style x:Key="LabelStyleSmall" TargetType="Label">
<Setter Property="TextColor" Value="#41a4dc"/>
<Setter Property="Font" Value="Small"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="HorizontalOptions" Value="Center"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<controls:Navigation/>
</Grid>
<Grid RowSpacing="0" Grid.Row="1" Padding="10,10,10,0">
<Grid.RowDefinitions>
<RowDefinition Height="145*" />
<RowDefinition Height="415*" />
<RowDefinition Height="2*" />
<RowDefinition Height="88*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" RowSpacing="10" BackgroundColor="#ed004a">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="#ed004a" Padding="30,0,0,0">
<Label Text="Your personal exam history information"
Style="{StaticResource LabelStyle}"
HorizontalOptions="StartAndExpand"/>
</Grid>
<Grid Grid.Row="1"
BackgroundColor="#0075c1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text=""
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
Text="Type:"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="2"
Text="Created:"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="3"
Text="Finished:"
Style="{StaticResource LabelStyle}"/>
</Grid>
</Grid>
<Grid Grid.Row="1">
<ScrollView>
<Grid x:Name="GridExams">
</Grid>
</ScrollView>
</Grid>
<BoxView Grid.Row="2" Color="#0075c1" WidthRequest="100" HeightRequest="2"/>
<Grid Grid.Row="3" Padding="0,0,0,10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="40*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"
BackgroundColor="{Binding DeleteButtonBackgroundColor}"
Padding="30,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
x:Name="LabelDeleteSelectedExamsPartOne"
Text="{Binding DeleteButtonText}"
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
x:Name="LabelDeleteSelectedExamsPartTwo"
Text=""
Style="{StaticResource LabelStyle}"
Font="Large"/>
<Grid.GestureRecognizers IsEnabled="{Binding DeleteButtonIsEnabled}">
<TapGestureRecognizer
Command="{Binding DeleteSelectedExamsCommand}"/>
</Grid.GestureRecognizers>
</Grid>
<Grid Grid.Column="2"
BackgroundColor="#0075c1"
Padding="30,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
x:Name="LabelCreateNewExamPartOne"
Text="Create New Exam "
Style="{StaticResource LabelStyle}"/>
<Label Grid.Column="1"
x:Name="LabelCreateNewExamPartTwo"
Text=""
Style="{StaticResource LabelStyle}"
Font="Large"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding CreateNewExamCommand}"/>
</Grid.GestureRecognizers>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid Grid.Row="1"
IsVisible="{Binding IsLoading}"
BackgroundColor="Black"
Opacity="0.25">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ActivityIndicator Grid.Row="0"
IsVisible="{Binding IsLoading}"
IsRunning="{Binding IsLoading}"
VerticalOptions="End"
HorizontalOptions="Center"/>
<Label Grid.Row="1"
Text="Please wait..."
TextColor="White"
VerticalOptions="Start"
HorizontalOptions="Center"/>
</Grid>
</Grid>
</ContentPage>
Method details that creates the grid dynamically:
private void CrateExamsGridDynamically()
{
GridExams.RowDefinitions = new RowDefinitionCollection();
GridExams.BackgroundColor = Color.White;
GridExams.Padding = new Thickness(0, 5, 0, 5);
Grid childContainer = new Grid();
childContainer.HorizontalOptions = LayoutOptions.CenterAndExpand;
childContainer.VerticalOptions = LayoutOptions.CenterAndExpand;
childContainer.BackgroundColor = Color.White;
childContainer.RowDefinitions = new RowDefinitionCollection();
childContainer.ColumnDefinitions = new ColumnDefinitionCollection()
{
new ColumnDefinition
{
Width =new GridLength(1, GridUnitType.Star)
},
new ColumnDefinition
{
Width=new GridLength(4, GridUnitType.Star)
}
};
GridExams.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
List<Exam> exams = App.ExamService.GetExams();
int top = 0;
foreach (var exam in exams)
{
childContainer.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(60, GridUnitType.Absolute)
});
exam.StartDateText = exam.StartDate.HasValue ? exam.StartDate.Value.ToString("dd/MM/yy") : string.Empty;
exam.FinishedDateText = exam.FinishedDate.HasValue ? exam.FinishedDate.Value.ToString("dd/MM/yy") : "In Progress >";
string examType = string.Empty;
switch (exam.Type)
{
case ExamTypes.Undefined:
break;
case ExamTypes.Part1:
examType = "Part 1";
break;
case ExamTypes.Part2:
examType = "Part 2";
break;
case ExamTypes.Both:
break;
default:
break;
}
#region [ Left Grandchild Container ]
Grid grandChildContainerLeft = new Grid();
grandChildContainerLeft.BackgroundColor = Constants.CustomColour.RcpPurple;
grandChildContainerLeft.Padding = new Thickness(1, 1, 1, 1);
#region [ Left Great Grandchild Container ]
Grid greatGrandChildContainerLeft = new Grid();
// TapGestureRecognizer for Left Container
var grandChildContainerLeftTapGestureRecognizer = new TapGestureRecognizer();
grandChildContainerLeftTapGestureRecognizer.Tapped += GrandChildContainerLeftTapGestureRecognizer_Tapped;
greatGrandChildContainerLeft.GestureRecognizers.Add(grandChildContainerLeftTapGestureRecognizer);
greatGrandChildContainerLeft.BackgroundColor = Color.White;
greatGrandChildContainerLeft.Children.Add(new Label
{
Text = exam.Name,
TextColor = Constants.CustomColour.RcpPurple,
FontAttributes = FontAttributes.Bold,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand
}, 0, 0);
// This is to carry exam id
greatGrandChildContainerLeft.Children.Add(new Label
{
Text = exam.Id.ToString(),
IsVisible = false
}, 0, 0);
#endregion
grandChildContainerLeft.Children.Add(greatGrandChildContainerLeft, 0, 0);
#endregion
#region [ Right Grandchild Container ]
Grid grandChildContainerRight = new Grid();
grandChildContainerRight.BackgroundColor = Constants.CustomColour.RcpBlue;
grandChildContainerRight.Padding = new Thickness(1, 1, 1, 1);
#region [ Right Great Grandchild Container ]
Grid greatGrandChildContainerRight = new Grid();
// TapGestureRecognizer for Right Container
var grandChildContainerRightTapGestureRecognizer = new TapGestureRecognizer();
grandChildContainerRightTapGestureRecognizer.Tapped += GrandChildContainerRightTapGestureRecognizer_Tapped;
greatGrandChildContainerRight.GestureRecognizers.Add(grandChildContainerRightTapGestureRecognizer);
greatGrandChildContainerRight.BackgroundColor = Color.White;
// We need three columns for each child grid
greatGrandChildContainerRight.ColumnDefinitions = new ColumnDefinitionCollection()
{
new ColumnDefinition
{
Width =new GridLength(1, GridUnitType.Star)
},
new ColumnDefinition
{
Width=new GridLength(1, GridUnitType.Star)
},
new ColumnDefinition
{
Width=new GridLength(2, GridUnitType.Star)
}
};
// This is for type
greatGrandChildContainerRight.Children.Add(new Label
{
Text = examType,
TextColor = Constants.CustomColour.RcpBlue,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
}, 0, 0); // Exam type: the first column
// This is to carry exam id
greatGrandChildContainerRight.Children.Add(new Label
{
Text = exam.Id.ToString(),
IsVisible = false
}, 0, 0);
// This is for created date
greatGrandChildContainerRight.Children.Add(new Label
{
Text = exam.StartDateText,
TextColor = Constants.CustomColour.RcpBlue,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
}, 1, 0); // Created: the second column
// This is for finished date
greatGrandChildContainerRight.Children.Add(new Label
{
Text = exam.FinishedDateText,
TextColor = Constants.CustomColour.RcpBlue,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
}, 2, 0); // Finished: the third column
#endregion
grandChildContainerRight.Children.Add(greatGrandChildContainerRight, 0, 0);
#endregion
childContainer.Children.Add(grandChildContainerLeft, 0, top); // First Column for grandChildContainerLeft
childContainer.Children.Add(grandChildContainerRight, 1, top); // Second Column for grandChildContainerRight
top++;
}
GridExams.Children.Add(childContainer, 0, 0);
}