Xamarin Forms Grid Positioning - c#

My code creates the grid just like I want to, but my issue is the formatting of it. For example, the below syntax has the grid (using iPhone emulator) start at almost the half-way point of the screen. From best of I can tell, I am only declaring the width of the date column as I do not want it to be drug onto 2 lines if it is a 2 digit month or 2 digit year.
What would be the best way to alter this code so that the grid will span the entire screen in Up & Down format, not Horizontal.
private void LoadInvoiceGrid()
{
List<InvoiceHistory> IH = new List<InvoiceHistory>();
IH = dal.GetInvoices(company);
Grid usergrid = new Grid();
//Adding in this line makes no diff to the display of the grid
usergrid.VerticalOptions = LayoutOptions.FillAndExpand;
//
usergrid.Padding = new Thickness(10, 120, 0, 0);
usergrid.RowDefinitions.Add(new RowDefinition { Height = 50 });
foreach (var item in IH)
usergrid.RowDefinitions.Add(new RowDefinition { Height = 50 });
usergrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });
usergrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });
usergrid.ColumnDefinitions.Add(new ColumnDefinition { Width = 50 });
Label invoicenumHeader = new Label
{
Text = "Invoice #"
};
Label invoiceamountHeader = new Label
{
Text = "Amount"
};
Label invoiceduedateHeader = new Label
{
Text = "Due Date"
};
Grid.SetColumn(invoicenumHeader, 1);
Grid.SetColumn(invoiceamountHeader, 2);
Grid.SetColumn(invoiceduedateHeader, 3);
usergrid.Children.Add(invoicenumHeader);
usergrid.Children.Add(invoiceamountHeader);
usergrid.Children.Add(invoiceduedateHeader);
int rowIndex = 1;
foreach (var item in IH)
{
string date = item.invoiceduedate.Date.ToShortDateString();
Label invoicenum = new Label
{
Text = item.invoicenum.ToString()
};
Label invoiceamount = new Label
{
Text = "$" + item.invoiceamt.ToString("0.##")
};
Label invoiceduedate = new Label
{
Text = date
};
Grid.SetRow(invoicenum, rowIndex);
Grid.SetRow(invoiceamount, rowIndex);
Grid.SetRow(invoiceduedate, rowIndex);
Grid.SetColumn(invoicenum, 1);
Grid.SetColumn(invoiceamount, 2);
Grid.SetColumn(invoiceduedate, 3);
usergrid.Children.Add(invoicenum);
usergrid.Children.Add(invoiceamount);
usergrid.Children.Add(invoiceduedate);
rowIndex++;
}
InvoiceGrid = usergrid;
}
EDIT
In my XAML I have the Vertical Option set to Fill And Expand and it is not making any difference. See my XAML for the page.
<?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="Pages.DoIt" >
<ContentPage.Content>
<StackLayout Orientation="Vertical" Padding="30" Spacing="40">
<Label TextColor="#77d065" FontSize = "8" Text="Yes, Test, Text" />
<Label TextColor="Blue" FontSize="8" Text="{Binding CompanyWelcomeMessage}" />
<ContentView VerticalOptions="FillAndExpand" Content="{Binding InvoiceGrid,Mode=TwoWay}" Padding="0,10,0,0"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Related

How to remove default margins from microcharts (xamarin)?

I want to remove the default margins in microcharts and stretch the graphic to the end of the frame using xamarin.
My xaml code is:
<Frame
BorderColor="White"
Margin="10,0,10,0"
CornerRadius="10"
HasShadow="True"
BackgroundColor="Transparent">
<StackLayout>
<forms:ChartView x:Name="Chart1"
HeightRequest="150"
HorizontalOptions="FillAndExpand"/>
</StackLayout>
</Frame>
My c# code is:
List<EntryMicrocharts> entries = new List<EntryMicrocharts>
{
new EntryMicrocharts ((float)TemperaturesList[0].AvgTemperature)
{
Color=SKColor.Parse("#ffffff"),
Label = Info1Forecast,
ValueLabel = Math.Round((float)TemperaturesList[0].AvgTemperature,0).ToString() + "°C",
ValueLabelColor = SKColor.Parse("#ffffff")
},....... more same code here
};
Chart1.Chart = new LineChart()
{
Entries = entries,
PointSize = 30,
LineSize = 12,
LabelTextSize = 35f,
LabelOrientation = Orientation.Horizontal,
ValueLabelOrientation = Orientation.Horizontal,
BackgroundColor = SKColors.Transparent,
LabelColor = SKColor.Parse("#ffffff"),
};
}
}
How to stretch the graphic to the end of the frame ?
I try with Margin = "0,0,0,0" in xaml code but this not work for me.
Is there a way to remove margins ?
This is a known issue with width of LineChart. You can either fix this bug in MicroCharts or try changing to another type of charts if that works for you, like BarChart:
Chart1.Chart = new BarChart()
{
Entries = entries,
LabelTextSize = 35f,
LabelOrientation = Orientation.Horizontal,
ValueLabelOrientation = Orientation.Horizontal,
BackgroundColor = SKColors.Transparent,
LabelColor = SKColor.Parse("#FFFFFF")
};
Also, add appropriate padding in XAML, like Padding = "2".

Xamarin Forms Grid Row Height Much Bigger Than Content

I am dynamically generating a grid and am filling it with content through C# code. The code is as follows:
<?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="WPapp.Views.Home"
x:Name="HomeHeader">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Refresh"
x:Name="refreshButton"
Clicked="refreshButton_Clicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<ScrollView>
<StackLayout Margin="10"
HorizontalOptions="Center"
VerticalOptions="FillAndExpand"
x:Name="HomeContainer"
CompressedLayout.IsHeadless="true">
<Label Text="Featured Posts"
FontSize="Title"
FontAttributes="Bold"
Margin="0, 20, 10, 0"/>
<StackLayout x:Name="FeaturedContainer"
CompressedLayout.IsHeadless="true">
</StackLayout>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
int columnNum = 0;
int rowNum = 0;
foreach (var category in categoryList)
{
Grid postGrid = new Grid();
var column = new ColumnDefinition();
column.Width = new GridLength(5, GridUnitType.Star);
postGrid.ColumnDefinitions.Add(column);
postGrid.ColumnDefinitions.Add(column);
double division = featuredPosts.Count / 2;
double rowCount = Math.Ceiling(division);
for (int i = 0; i < rowCount; i++)
{
var row = new RowDefinition();
row.Height = GridLength.Auto;
postGrid.RowDefinitions.Add(row);
}
foreach (var item in featuredPosts)
{
Frame featuredFrame = new Frame();
featuredFrame.BorderColor = Color.Gray;
featuredFrame.CornerRadius = 5;
featuredFrame.Padding = 20;
Label postTitle = new Label();
postTitle.FontSize = Device.GetNamedSize(NamedSize.Subtitle, typeof(Label));
postTitle.FontAttributes = FontAttributes.Bold;
BoxView titleSeparator = new BoxView();
titleSeparator.Color = Color.Gray;
titleSeparator.HeightRequest = 1;
titleSeparator.HorizontalOptions = LayoutOptions.Fill;
Image postFeaturedImage = new Image();
postFeaturedImage.Aspect = Aspect.AspectFill;
BoxView imageSeparator = new BoxView();
imageSeparator.Color = Color.Gray;
imageSeparator.HeightRequest = 2;
imageSeparator.HorizontalOptions = LayoutOptions.Fill;
Label publishDate = new Label();
publishDate.FontSize = Device.GetNamedSize(NamedSize.Caption, typeof(Label));
StackLayout postDetails = new StackLayout();
postDetails.Children.Add(postTitle);
postDetails.Children.Add(titleSeparator);
postDetails.Children.Add(postFeaturedImage);
postDetails.Children.Add(imageSeparator);
postDetails.Children.Add(publishDate);
featuredFrame.Content = postDetails;
if ((featuredPosts.First() == item) && !(featuredPosts.Count() % 2 == 0))
{
postGrid.Children.Add(featuredFrame, columnNum, rowNum);
Grid.SetColumnSpan(featuredFrame, 2);
columnNum++;
}
else
{
postGrid.Children.Add(featuredFrame, columnNum, rowNum);
Grid.SetColumnSpan(featuredFrame, 1);
}
columnNum++;
if (columnNum == 2)
{
rowNum++;
columnNum = 0;
}
}
FeaturedContainer.Children.Add(postGrid);
columnNum = 0;
rowNum = 0;
}
With this code, this is the result I am getting:
As you can see, the top-left grid height is sized correctly as it is just big enough to fit its children. This is how it should be.
However, the problem is, sometimes the grid cell becomes too big, this is shown in the bottom-left and bottom-right cells. It is too tall! This is only for some of the cells.
What am I doing wrong and how can I fix this so the grid height is just big enough, not too big.

Xamarin grid and StackLayout

I would like to know how to put a stacklayout into a grid case of xamarin forms and repeat tha pattern.
I decleare in my xaml my grid and the stacklayout.
<Grid x:Name="MyGrid" RowSpacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout x:Name="MyLayout">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</StackLayout.GestureRecognizers>
</StackLayout>
</Grid>
Then in my c# i wannt to create
var test = new List<Product>
{
new Product() {Desc = "DESC", Brand= "HelloWorld", Price= "30", Uri = "UriToPicture" },
new Product() {Desc = "DESC2", Brand= "HelloWorld2", Price= "30", Uri = "UriToPicture" }
};
Image PicProd = new Image { Aspect = Aspect.AspectFit };
PicProd.Source = FileImageSource.FromUri(new Uri(test[0].Uri));
Label Name= new Label { Text = test[0].Marque.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
Label Desc = new Label { Text = test[0].Desc.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
Label Price = new Label { Text = test[0].Prix.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
MyLayout.Children.Add(PicProd);
MyLayout.Children.Add(Name);
MyLayout.Children.Add(Desc);
MyLayout.Children.Add(Price);
MyGrid.Children.Add(MyLayout, 0, 0);
MyGrid.Children.Add(MyLayout, 0, 1);
Content = MyGrid;
So I have two stacklayout elements that i want to display on two colomns(side by side) but i don't succed to display them correctly
You can set the Grid.Row and Grid.Column on elements to position them inside the grid. These are 0-based indexers. So in your case you could set the StackLayout as follows:
<StackLayout x:Name="MyLayout" Grid.Row="0" Grid.Column="0">
And in the next you could put:
<StackLayout x:Name="MyLayout" Grid.Row="0" Grid.Column="1">
UPDATE:
You cannot add the same instance of a control to a page twice, which is why only one of your items is showing up. You should instantiate 2 actual instances of your StackLayout. Remove the StackLayout from your XAML and declare it in code-behind. Then create 2 separate label instances and add those to the appropriate StackLayout. It should look something like this:
var test = new List<Product>
{
new Product() {Text1 = "DESC", Text2= "HelloWorld" },
new Product() {Text1 = "DESC2", Text2= "HelloWorld2" }
};
MyGrid.BackgroundColor = Color.Yellow;
var Name = new Label { Text = test[0].Text1.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
var Desc = new Label { Text = test[0].Text2.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
var MyLayout = new StackLayout();
MyLayout.BackgroundColor = Color.Red;
MyLayout.Children.Add(Name);
MyLayout.Children.Add(Desc);
MyGrid.Children.Add(MyLayout, 0, 0);
var Name2 = new Label { Text = test[0].Text1.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
var Desc2 = new Label { Text = test[0].Text2.ToString(), TextColor = Color.Black, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
var MyLayout2 = new StackLayout();
MyLayout2.BackgroundColor = Color.Blue;
MyLayout2.Children.Add(Name2);
MyLayout2.Children.Add(Desc2);
MyGrid.Children.Add(MyLayout2, 1, 0);
Another thing to keep in mind, the parameters for the Children.Add call want the column as the first parameter and then the row. Additionally you could use this extension method to simplify the process of adding children with spans etc.
public static class GridExtension
{
public static void AddChild(this Grid grid, View view, int row, int column, int rowspan = 1, int columnspan = 1)
{
if (row < 0) throw new ArgumentOutOfRangeException(nameof(row));
if (column < 0) throw new ArgumentOutOfRangeException(nameof(column));
if (rowspan <= 0) throw new ArgumentOutOfRangeException(nameof(rowspan));
if (columnspan <= 0) throw new ArgumentOutOfRangeException(nameof(columnspan));
if (view == null) throw new ArgumentNullException(nameof(view));
Grid.SetRow((BindableObject)view, row);
Grid.SetRowSpan((BindableObject)view, rowspan);
Grid.SetColumn((BindableObject)view, column);
Grid.SetColumnSpan((BindableObject)view, columnspan);
grid.Children.Add(view);
}
}
So I have two Stacklayout elements that i want to display on two colomns(side by side) but i don't succed to display them correctly
The problem is that you don't have two Stacklayout elements. Instead, you have one single instance that you pass two times to the grid using Add method.
If you want a second Stacklayout side by side, first create a new instance of a Stacklayout either in code or in XAML:
<StackLayout x:Name="MySecondLayout">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</StackLayout.GestureRecognizers>
</StackLayout>
And pass it to your grid using Add method:
//... Populate "MySecondLayout" as you did for "MyLayout"
// Add your two layouts to the grid
MyGrid.Children.Add(MyLayout, 0, 0);
MyGrid.Children.Add(MySecondLayout, 0, 1);
If you want to use the exact same Stacklayout twice side by side, you must create two different instances of a Stacklayout.

How can I programmatically set the font colour of only one element of a listview?

I am trying to change the font colour of a specific item of my listview in code and I am not sure how to approach it. This is what I have so far:
lv_options.ItemsSource = new Options[] {
new Options { Text = "Delete" },
new Options { Text = "Rename"} ,
new Options { Text = "Order: Move up" },
new Options { Text = "Order: Move down"}
};
if (act.item.SectionPosition >= act.lst_sections.Count() || act.item.SectionPosition <= 1)
{
foreach (Options op in lv_options.ItemsSource)
{
if(op.Text.Equals("Order: Move up"))
{
lv_options.HeaderTemplate.SetValue....???
}
}
}
This is my listview
<ListView x:Name="lv_options">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="10, 15, 0, 15">
<Label Font = "20" Text="{Binding Text}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You will need to identify which control you want to change.
Then find the control to add the attribute.
Example:
Label label = (Label)ListViewID.FindControl("LabelID");
label.Attributes.Add("color", "red");
int index = 1;
ListViewItem item = this.lv_options.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
item.Foreground = Brushes.Green;

Controlled Frame Width Size In A Horizontal StackLayout

I am trying to create a set of stacked horizontal StackLayouts composed of Frames with differing widths. The end goal is to create a Schedule View (multiple calendars viewed at once) not unlike what is possible in Outlook (see attached image).
Desired Output: http://i.stack.imgur.com/1c0mu.png
In trying to do this I noticed that the Width of Frames added to a Horizontal StackLayout will match the WidthRequest only if all of the Frames have the same exact width. If the widths of the Frames differ then the Width and WidthRequests don't match.
Here is the XAML:
<?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="XamarinSample.SamplePage1">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<ScrollView x:Name="FrozenBandDataScrollView"
Orientation="Horizontal">
<StackLayout VerticalOptions="Start"
HorizontalOptions="Start"
Orientation="Vertical"
Spacing="0"
BackgroundColor="Silver"
WidthRequest="3600"
x:Name="FrozenBandDataStackLayout">
</StackLayout>
</ScrollView>
</ContentPage>
Here is the Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinSample
{
public partial class SamplePage1 : ContentPage
{
TapGestureRecognizer tapFrameRecognizer = new TapGestureRecognizer();
public SamplePage1()
{
InitializeComponent();
addDataPoints();
}
public void addDataPoints()
{
tapFrameRecognizer.Tapped += (s, e) =>
{
Frame f = s as Frame;
Label l = f.Content as Label;
l.Text = "R:" + f.WidthRequest;
l.Text += ", W: " + f.Width;
l.Text += "\nR: " + f.HeightRequest;
l.Text += ", H: " + f.Height;
};
FrozenBandDataStackLayout.Children.Add(getStackLayoutWithDimensions(70, 3600));
FrozenBandDataStackLayout.Children.Add(getStackLayoutWithDimensions(70, 3600));
FrozenBandDataStackLayout.Children.Add(getStackLayoutWithDimensions(70, 3600));
}
public static double randomNumber(int start, int end){return (new Random()).Next(start, end);}
public StackLayout getStackLayoutWithDimensions(double height, double width)
{
StackLayout sl = new StackLayout {
VerticalOptions = LayoutOptions.Start,
HorizontalOptions = LayoutOptions.Start,
Orientation = StackOrientation.Horizontal,
WidthRequest = width,
HeightRequest = height,
Spacing = 0
};
//OPTION 1: randomly calculated width (total = 3600) -- does not work :(
int minFrameWidth = 1;
int maxFrameWidth = 500;
double currentWidth = 0;
while ((currentWidth + maxFrameWidth) < width)
{
double frameWidth = randomNumber(minFrameWidth, maxFrameWidth);
currentWidth += frameWidth;
sl.Children.Add(getFrameWithDimensions(height, frameWidth));
}
sl.Children.Add(getFrameWithDimensions(height, width-currentWidth));
//OPTION 2: specific homogeneous width (total = 3600) -- works :)
/*
for (int i = 0; i < 12; i++)
{
sl.Children.Add(getFrameWithDimensions(height, 300));
}
*/
//OPTION 3: specific altering width (total = 3600) -- does not work :(
/*
for (int i = 0; i < 12; i++)
{
if (i % 2 == 0) {
sl.Children.Add(getFrameWithDimensions(height, 200));
}else
{
sl.Children.Add(getFrameWithDimensions(height, 400));
}
}
*/
return sl;
}
public Frame getFrameWithDimensions(double height, double width)
{
Frame frame = new Frame
{
BackgroundColor = Color.Gray,
OutlineColor = Color.Black,
HasShadow = false,
HorizontalOptions = LayoutOptions.Start,
WidthRequest = width,
VerticalOptions = LayoutOptions.Start,
HeightRequest = height,
Content = new Label
{
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center,
TextColor = Color.Black,
FontFamily = "Arial",
FontSize = 8,
Text = "test"
}
};
frame.GestureRecognizers.Add(tapFrameRecognizer);
return frame;
}
}
}
Here are the three different outputs: http://forums.xamarin.com/discussion/74391/controlled-frame-width-size-in-a-horizontal-stacklayout
Does anyone know a way to assure that the WidthRequest matches the actual Width?
Also, can anyone think of another possible Xamarin Forms solution? I've tried using a Grid but it was really slow (as it's not meant for this type of use). It would be nice to have something with data binding like a horizontal ListView.
Note: This app would need to work for iOS, Windows UWP, and possibly Android.

Categories

Resources