Xamarin - XAML Grid UI overwriting on each other - xaml

I am creating a UI using a grid in Xamarin which I have put in StackLayout.
Below is the following code for xaml.
program.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="LoginPage.Page">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<StackLayout BackgroundColor="#3a4851">
<Label Text="Identifications" TextColor="White" FontSize="15" Margin="10" />
</StackLayout>
<StackLayout>
<Grid x:Name="identificationGridLayout" HorizontalOptions="Center"></Grid>
</StackLayout>
<StackLayout BackgroundColor="#3a4851">
<Label Text="Deciles" TextColor="White" FontSize="15" Margin="10" />
</StackLayout>
<StackLayout>
<Grid x:Name="decileGridLayout" HorizontalOptions="Center"></Grid>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I am creating the Grid header and data programatically.
program.cs
public partial class Page : ContentPage
{
private LoadingPopUp popUp;
private Repository repository = new Repository();
private JObject jResult;
private List<string> rowHeader;
private List<PrescriberIdentitifcation> prescriberIdentificationValue;
private List<PrescriberDecile> prescriberDecileValue;
public Page() { InitializeComponent(); }
public Page(string guid)
{
InitializeComponent();
FetchDataForDetail(guid);
}
async void FetchDataForDetail(string guid)
{
try
{
popUp = new LoadingPopUp("Loading data ...");
await PopupNavigation.PushAsync(popUp);
//Get Identification Data for prescriber
JObject identificationResult = await GetRepositoryDetailData(guid);
var identificationdata = JsonConvert.DeserializeObject<PrescriberIdentificationList>(identificationResult.ToString());
prescriberIdentificationValue = identificationdata.value;
int index = 0;
foreach (var obj in identificationResult["value"])
{
prescriberIdentificationValue[index].vcm_type_name = (string)obj["vcm_type#OData.Community.Display.V1.FormattedValue"];
index++;
}
drawIdentificationGrid();
//Get Deciles Data for prescriber
JObject decileResult = await GetRepositoryDetailData(guid);
var deciledata = JsonConvert.DeserializeObject<PrescriberIdentificationList>(decileResult.ToString());
prescriberIdentificationValue = deciledata.value;
Debug.WriteLine("data prescriberIdentificationValue : " + prescriberIdentificationValue);
drawDecilesGrid();
await PopupNavigation.PopAllAsync();
}
catch (Exception ex) {
Debug.WriteLine("error in identification loading : " + ex.Message);
await PopupNavigation.PopAllAsync();
}
}
public async Task<JObject> GetRepositoryDetailData(string guid, string entity, string filter)
{
try
{
jResult = await repository.Retrieve(GlobalVariables.AuthToken, entity, filter + guid);
return jResult;
}
catch (Exception err)
{
Debug.WriteLine(err.Message);
await PopupNavigation.PopAllAsync();
await DisplayAlert("Error", "Oops something went wrong", "Ok");
}
return jResult;
}
void drawIdentificationGrid()
{
try
{
rowHeader = new List<string>{"Type", "Number", "License State", "Sampleability","Expiration Date","License Status" };
drawGridHeader(identificationGridLayout,1, rowHeader.Count,rowHeader);
for (int rowIndex = 1; rowIndex <= prescriberIdentificationValue.Count; rowIndex++)
{
var datatypeLabel = new Label { Text = prescriberIdentificationValue[rowIndex-1].vcm_type_name.ToString(),FontSize=12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
var datanumberLabel = new Label { Text = prescriberIdentificationValue[rowIndex-1].vcm_name.ToString(),FontSize=12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
var datalicenseStateLabel = new Label { Text = (prescriberIdentificationValue[rowIndex-1]._vcm_licensestate_value != null) ? prescriberIdentificationValue[rowIndex-1]._vcm_licensestate_value : "-" , FontSize=12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
var datasampleabiltiyLabel = new Label { Text = (prescriberIdentificationValue[rowIndex - 1].vcm_sampleability == false) ? "No": "Yes", FontSize=12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
var dataexpirationDateLabel = new Label { Text = (prescriberIdentificationValue[rowIndex-1].vcm_expirationdate != null) ? prescriberIdentificationValue[rowIndex-1].vcm_expirationdate : "-", FontSize=12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
Debug.WriteLine("data datatypeLabel {0} datanumberLabel {1} datalicenseStateLabel {2} datasampleabiltiyLabel {3} dataexpirationDateLabel {4} rowIndex {5}",datatypeLabel.Text,datanumberLabel.Text,datalicenseStateLabel.Text, datasampleabiltiyLabel.Text, dataexpirationDateLabel.Text, rowIndex);
identificationGridLayout.Children.Add(datatypeLabel, 0, rowIndex);
identificationGridLayout.Children.Add(datanumberLabel, 1, rowIndex);
identificationGridLayout.Children.Add(datalicenseStateLabel, 2, rowIndex);
identificationGridLayout.Children.Add(datasampleabiltiyLabel, 3, rowIndex);
identificationGridLayout.Children.Add(dataexpirationDateLabel, 4, rowIndex);
}
}
catch (Exception ex) { Debug.WriteLine("Error in drawing Identifications: "+ ex.Message);}
}
void drawDecilesGrid()
{
try
{
rowHeader = new List<string>{"Quarter", "Decile Type", "Decile", "Rank","Organization Type" };
drawGridHeader(decileGridLayout,1, rowHeader.Count, rowHeader);
//for (int rowIndex = 1; rowIndex <= prescriberIdentificationValue.Count; rowIndex++)
//{
// var datatypeLabel = new Label { Text = prescriberIdentificationValue[rowIndex - 1].vcm_type_name.ToString(), FontSize = 12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// var datanumberLabel = new Label { Text = prescriberIdentificationValue[rowIndex - 1].vcm_name.ToString(), FontSize = 12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// var datalicenseStateLabel = new Label { Text = (prescriberIdentificationValue[rowIndex - 1]._vcm_licensestate_value != null) ? prescriberIdentificationValue[rowIndex - 1]._vcm_licensestate_value : "-", FontSize = 12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// var datasampleabiltiyLabel = new Label { Text = (prescriberIdentificationValue[rowIndex - 1].vcm_sampleability == false) ? "No" : "Yes", FontSize = 12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// var dataexpirationDateLabel = new Label { Text = (prescriberIdentificationValue[rowIndex - 1].vcm_expirationdate != null) ? prescriberIdentificationValue[rowIndex - 1].vcm_expirationdate : "-", FontSize = 12, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// Debug.WriteLine("data datatypeLabel {0} datanumberLabel {1} datalicenseStateLabel {2} datasampleabiltiyLabel {3} dataexpirationDateLabel {4} rowIndex {5}",datatypeLabel.Text,datanumberLabel.Text,datalicenseStateLabel.Text, datasampleabiltiyLabel.Text, dataexpirationDateLabel.Text, rowIndex);
// identificationGridLayout.Children.Add(datatypeLabel, 0, rowIndex);
// identificationGridLayout.Children.Add(datanumberLabel, 1, rowIndex);
// identificationGridLayout.Children.Add(datalicenseStateLabel, 2, rowIndex);
// identificationGridLayout.Children.Add(datasampleabiltiyLabel, 3, rowIndex);
// identificationGridLayout.Children.Add(dataexpirationDateLabel, 4, rowIndex);
//}
}
catch (Exception ex) { Debug.WriteLine("Error in drawing Identifications: "+ ex.Message);}
}
void drawGridHeader(Grid gridLayout, int rowIndexLength, int columnIndexLength, List<string> rowHeaders)
{
try
{
gridLayout.RowDefinitions = new RowDefinitionCollection();
gridLayout.ColumnDefinitions = new ColumnDefinitionCollection();
for (int rowIndex = 0; rowIndex < rowIndexLength; rowIndex++)
{
gridLayout.RowDefinitions.Add(new RowDefinition());
}
for (int columnIndex = 0; columnIndex <= columnIndexLength; columnIndex++)
{
gridLayout.ColumnDefinitions.Add(new ColumnDefinition());
}
for (int i = 0; i < columnIndexLength; i++)
{
var label = new Label { Text = rowHeaders[i], FontSize = 14, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
identificationGridLayout.Children.Add(label, i, 0);
}
}
catch (Exception ex) { Debug.WriteLine("Error in drawing grid header: "+ ex.Message);}
}
}
}
drawGridHeader() is common to creating Header for different grids. Data for the cell is passed in different functions and grid reference is passed to it.
Ex: -
rowHeader = new List<string>{"Quarter", "Decile Type", "Decile", "Rank","Organization Type" };
drawGridHeader(decileGridLayout,1, rowHeader.Count, rowHeader);
But after fetching the data, The Grid is over writing on each other.
I tried creating manual grid with row item and they are stacking properly in order but when programmatically doing it, grid is stacking upon each other.
It should been below the Label Decile.

Inside the last for-loop in drawGridHeader(), you're not referencing the passed in grid when adding the labels:
for (int i = 0; i < columnIndexLength; i++)
{
var label = new Label { Text = rowHeaders[i], FontSize = 14, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
// This references the wrong Grid
// identificationGridLayout.Children.Add(label, i, 0);
gridLayout.Children.Add(label, i, 0);
}

Related

Create multiple frames in code behind in Xamarin.Forms

I want to create multiple frames in code-behind, but when creating frames in loop and adding elements in content, only one frame has all elements and other frames are empty! why?
My code is:
private void searchResults_ItemTapped(object sender, ItemTappedEventArgs e)
{
searchResults.IsVisible = false;
Indexes Indexes = (Indexes)searchResults.SelectedItem;
_viewModel.Items.Add(db.RequestToJson(Indexes.Index));
searchbar.Text = string.Empty;
StackLayout Words = new StackLayout();
StackLayout WordDetail = new StackLayout();
foreach (var dt in _viewModel.Items)
{
AddTextToLabel(nameof(dt.Word), dt.Word, WordDetail);
var BaseLang = dt.BaseLang;
AddTextToLabel(nameof(BaseLang.Meaning), BaseLang.Meaning, WordDetail);
Words.Children.Add(new Frame { BackgroundColor = Color.FromHex("2196F3"), Padding = 5, HasShadow = false, Margin = new Thickness(10, 10, 80, 10), Content = new StackLayout { Children = { WordDetail } } });
}
SearchResult.Content = Words;
SearchResult.IsVisible = true;
}
private void AddTextToLabel(string title, string data, StackLayout worddetail)
{
worddetail.Children.Add(new Label { Text = title + ":", FontAttributes = FontAttributes.Bold, TextColor = Color.White });
worddetail.Children.Add(new Label { Text = data, TextColor = Color.White });
}
And here is the result:
you are using the same instance of WordDetail in every iteration of the loop
instead, create a new instance each time
foreach (var dt in _viewModel.Items)
{
StackLayout WordDetail = new StackLayout();
I reproduced your situation locally by copying your code. I solved it by moving the WordDetail declaration inside the foreach like so:
StackLayout Words = new StackLayout();
foreach (var dt in _viewModel.Items)
{
StackLayout WordDetail = new StackLayout();
AddTextToLabel(nameof(dt.Word), dt.Word, WordDetail);
var BaseLang = dt.BaseLang;
AddTextToLabel(nameof(BaseLang.Meaning), BaseLang.Meaning, WordDetail);
Words.Children.Add(new Frame { BackgroundColor = Color.FromHex("2196F3"), Padding = 5, HasShadow = false, Margin = new Thickness(10, 10, 80, 10), Content = new StackLayout { Children = { WordDetail } } });
}

How to show a badges count of ToolBarItem Icon in Xamarin Forms

It is not about how to show notification badges nor it's about to show toolbar item icon. It is clear question that how to show a badges count on a toolbar item icon. ?
I am sharing code to create ToolbarItem with icon in XF content page:
In cs File:
ToolbarItem cartItem = new ToolbarItem();
scanItem.Text = "My Cart";
scanItem.Order = ToolbarItemOrder.Primary;
scanItem.Icon = "carticon.png";
ToolbarItems.Add(cartItem );
In Xaml File:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Cart" Priority="0" x:Name="menu1">
</ToolbarItem>
</ContentPage.ToolbarItems>
Now I want to Place a badge count on the above added tool bar item icon. How it can be achieved ?
Placing badge icon's in the native toolbars is actually more effort than its worth. If I need a badge icon, I remove the navigation page.
NavigationPage.SetHasNavigationBar(myPageInstance, false);
Then I create my own toolbar from scratch. In this toolbar, I can overlay an image in there, you can also place a number in it as needed. For example.
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding IconCommand}" />
</Grid.GestureRecognizers>
<iconize:IconImage
Icon="fa-drawer"
IconColor="white"
IconSize="20" />
<Grid Margin="15,-15,0,0">
<iconize:IconImage Grid.Row="0"
HeightRequest="40"
WidthRequest="40"
Icon="fa-circle"
IconColor="red"
IsVisible="{Binding IsCircleVisible}"
IconSize="10" />
</Grid>
</Grid>
I use Iconize wtih FontAwesome for the icons
With the help of Xamarin Forum Discussion, I have achieved it. Read ad understand the complete discussion before implement it. Thank you "Slava Chernikoff", "Emanuele Sabetta", "Mirza Sikander", "Satish" to discuss and yours share code.
Setp 1: Create a Helper Class in PCL and install NGraphics package from nugget.
public class CartIconHelper
{
private static Graphic _svgGraphic = null;
public const string ResourcePath = "ToolBarAndroidBadge.Resources.cartIcon.svg";
private static PathOp[] RoundRect(NGraphics.Rect rect, double radius)
{
return new PathOp[]
{
new NGraphics.MoveTo(rect.X + radius, rect.Y),
new NGraphics.LineTo(rect.X + rect.Width - radius, rect.Y),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width, rect.Y + radius)),
new NGraphics.LineTo(rect.X + rect.Width, rect.Y + rect.Height - radius),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width - radius, rect.Y + rect.Height)),
new NGraphics.LineTo(rect.X + radius, rect.Y + rect.Height),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X, rect.Y + rect.Height - radius)),
new NGraphics.LineTo(rect.X, rect.Y + radius), new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + radius, rect.Y)),
new NGraphics.ClosePath()
};
}
public static string DrawCartIcon(int count, string path, double iconSize = 30, double scale = 2, string fontName = "Arial", double fontSize = 12, double textSpacing = 4)
{
var service = DependencyService.Get<IService>();
var canvas = service.GetCanvas();
if (_svgGraphic == null) using (var stream = typeof(CartIconHelper).GetTypeInfo().Assembly.GetManifestResourceStream(path))
_svgGraphic = new SvgReader(new StreamReader(stream)).Graphic;
//st = ReadFully(stream);
var minSvgScale = Math.Min(canvas.Size.Width / _svgGraphic.Size.Width, canvas.Size.Height / _svgGraphic.Size.Height) / 1.15;
var w = _svgGraphic.Size.Width / minSvgScale;
var h = _svgGraphic.Size.Height / minSvgScale;
_svgGraphic.ViewBox = new NGraphics.Rect(0, -14, w, h);
_svgGraphic.Draw(canvas);
if (count > 0)
{
var text = count > 99 ? "99+" : count.ToString();
var font = new NGraphics.Font(fontName, fontSize);
var textSize = canvas.MeasureText(text, font);
var textRect = new NGraphics.Rect(canvas.Size.Width - textSize.Width - textSpacing, textSpacing, textSize.Width, textSize.Height);
if (count < 10)
{
var side = Math.Max(textSize.Width, textSize.Height);
var elipseRect = new NGraphics.Rect(canvas.Size.Width - side - 2 * textSpacing, 0, side + 2 * textSpacing, side + 2 * textSpacing);
canvas.FillEllipse(elipseRect, NGraphics.Colors.Red);
textRect -= new NGraphics.Point(side - textSize.Width, side - textSize.Height) / 2.0;
}
else
{
var elipseRect = new NGraphics.Rect(textRect.Left - textSpacing, textRect.Top - textSpacing, textRect.Width + 2 * textSpacing, textSize.Height + 2 * textSpacing);
canvas.FillPath(RoundRect(elipseRect, 6), NGraphics.Colors.Red);
}
var testReact1= new NGraphics.Rect(20,12,0,0);
// canvas.DrawText(text, textRect + new NGraphics.Point(0, textSize.Height), font, NGraphics.TextAlignment.Center, NGraphics.Colors.Black);
canvas.DrawText("5", testReact1, font, NGraphics.TextAlignment.Left, NGraphics.Colors.White);
}
service.SaveImage(canvas.GetImage());
string imagePath = service.GetImage();
return imagePath;
// return st;
}
}
Step 2: Create a interface to IService in PCL
public interface IService
{
IImageCanvas GetCanvas();
void SaveImage(NGraphics.IImage image);
string GetImage();
}
Step 3 : Implement this interface in your Android project
class CanvasServices:IService
{
private readonly AndroidPlatform _platform;
public CanvasServices()
{
_platform = new AndroidPlatform();
}
public void SaveImage(IImage image)
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
var stream = new FileStream(filePath, FileMode.Create);
image.SaveAsPng(stream);
//bitmap.Compress(image., 100, stream);
stream.Close();
}
public string GetImage()
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
using (var streamReader = new StreamReader(filePath))
{
string content = streamReader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(content);
}
return filePath;
}
public IImageCanvas GetCanvas()
{
NGraphics.Size size = new NGraphics.Size(30);
return _platform.CreateImageCanvas(size);
}
public NGraphics.AndroidPlatform GetPlatform()
{
return _platform;
}
}
Setp 4: Now, use CartIcon Helper in your PCL project to show badges in TabBarItem.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var imagePath = CartIconHelper.DrawCartIcon(2, "ToolBarAndroidBadge.Resources.cartIcon.svg");
string deviceSepecificFolderPath = Device.OnPlatform(null, imagePath, null);
object convertedObject = new FileImageSourceConverter().ConvertFromInvariantString(deviceSepecificFolderPath);
FileImageSource fileImageSource = (FileImageSource)convertedObject;
ToolbarItem cartItem = new ToolbarItem();
cartItem.Text = "My Cart";
cartItem.Order = ToolbarItemOrder.Primary;
cartItem.Icon = fileImageSource;
ToolbarItems.Add(cartItem);
}
}
For any one who wants to add badge on toolbar item using custom ui try,
Instead of using default toolbar item, you can hide the default navigation bar by NavigationPage.SetHasNavigationBar(this, false);
in the constructor.
Then prepare the custom navigation bar with toolbar item with badge as mentioned in above answers.
If you are using master detail page, hiding default navigation bar will hide hamburger icon, so need to slide from left to see sliding menu. Alternate method would be place a button with hamburger icon in custom navigation bar, on button click use messaging center to present the sliding menu.
Example: On page in which hamburger button is clicked
private void Button_Clicked(object sender, System.EventArgs e)
{
MessagingCenter.Send(this, "presnt");
}
On MasterDetail page
MessagingCenter.Subscribe<YourPage>(this, "presnt", (sender) =>
{
IsPresented = true;
});
Before making IsPresented=true, check for sliding menu is not all-ready presented.
Check https://github.com/LeslieCorrea/Xamarin-Forms-Shopping-Cart for badge on toolbar item.
Implement below code to draw a ground circle with text over toolbar icon
BarButtonItemExtensions.cs
using CoreAnimation;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using UIKit;
namespace TeamCollaXform.Views.Services
{
public static class BarButtonItemExtensions
{
enum AssociationPolicy
{
ASSIGN = 0,
RETAIN_NONATOMIC = 1,
COPY_NONATOMIC = 3,
RETAIN = 01401,
COPY = 01403,
}
static NSString BadgeKey = new NSString(#"BadgeKey");
[DllImport(Constants.ObjectiveCLibrary)]
static extern void objc_setAssociatedObject(IntPtr obj, IntPtr key, IntPtr value, AssociationPolicy policy);
[DllImport(Constants.ObjectiveCLibrary)]
static extern IntPtr objc_getAssociatedObject(IntPtr obj, IntPtr key);
static CAShapeLayer GetBadgeLayer(UIBarButtonItem barButtonItem)
{
var handle = objc_getAssociatedObject(barButtonItem.Handle, BadgeKey.Handle);
if (handle != IntPtr.Zero)
{
var value = ObjCRuntime.Runtime.GetNSObject(handle);
if (value != null)
return value as CAShapeLayer;
else
return null;
}
return null;
}
static void DrawRoundedRect(CAShapeLayer layer, CGRect rect, float radius, UIColor color, bool filled)
{
layer.FillColor = filled ? color.CGColor : UIColor.White.CGColor;
layer.StrokeColor = color.CGColor;
layer.Path = UIBezierPath.FromRoundedRect(rect, radius).CGPath;
}
public static void AddBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor, bool filled = true, float fontSize = 11.0f)
{
if (string.IsNullOrEmpty(text))
{
return;
}
CGPoint offset = CGPoint.Empty;
if (backgroundColor == null)
backgroundColor = UIColor.Red;
var font = UIFont.SystemFontOfSize(fontSize);
if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
{
font = UIFont.MonospacedDigitSystemFontOfSize(fontSize, UIFontWeight.Regular);
}
var view = barButtonItem.ValueForKey(new NSString(#"view")) as UIView;
var bLayer = GetBadgeLayer(barButtonItem);
bLayer?.RemoveFromSuperLayer();
var badgeSize = text.StringSize(font);
var height = badgeSize.Height;
var width = badgeSize.Width + 5; /* padding */
//make sure we have at least a circle
if (width < height)
{
width = height;
}
//x position is offset from right-hand side
var x = view.Frame.Width - width + offset.X;
var badgeFrame = new CGRect(new CGPoint(x: x - 4, y: offset.Y + 5), size: new CGSize(width: width, height: height));
bLayer = new CAShapeLayer();
DrawRoundedRect(bLayer, badgeFrame, 7.0f, backgroundColor, filled);
view.Layer.AddSublayer(bLayer);
// Initialiaze Badge's label
var label = new CATextLayer();
label.String = text;
label.TextAlignmentMode = CATextLayerAlignmentMode.Center;
label.SetFont(CGFont.CreateWithFontName(font.Name));
label.FontSize = font.PointSize;
label.Frame = badgeFrame;
label.ForegroundColor = filled ? textColor.CGColor : UIColor.White.CGColor;
label.BackgroundColor = UIColor.Clear.CGColor;
label.ContentsScale = UIScreen.MainScreen.Scale;
bLayer.AddSublayer(label);
// Save Badge as UIBarButtonItem property
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, bLayer.Handle, AssociationPolicy.RETAIN_NONATOMIC);
}
public static void UpdateBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor)
{
var bLayer = GetBadgeLayer(barButtonItem);
if (string.IsNullOrEmpty(text) || text == "0")
{
bLayer?.RemoveFromSuperLayer();
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, new CAShapeLayer().Handle, AssociationPolicy.ASSIGN);
return;
}
var textLayer = bLayer?.Sublayers?.First(p => p is CATextLayer) as CATextLayer;
if (textLayer != null)
{
textLayer.String = text;
}
else
{
barButtonItem.AddBadge(text, backgroundColor, textColor);
}
}
}
}
ToolbarItemBadgeService.cs
using TeamCollaXform.Views.Services;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: Dependency(typeof(ToolbarItemBadgeService))]
namespace TeamCollaXform.Views.Services
{
/// <summary>
///
/// </summary>
public interface IToolbarItemBadgeService
{
void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor);
}
/// <summary>
///
/// </summary>
public class ToolbarItemBadgeService : IToolbarItemBadgeService
{
public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
{
Device.BeginInvokeOnMainThread(() =>
{
var renderer = Platform.GetRenderer(page);
if (renderer == null)
{
renderer = Platform.CreateRenderer(page);
Platform.SetRenderer(page, renderer);
}
var vc = renderer.ViewController;
var rightButtomItems = vc?.ParentViewController?.NavigationItem?.RightBarButtonItems;
var idx = rightButtomItems.Length - page.ToolbarItems.IndexOf(item) - 1; //Revert
if (rightButtomItems != null && rightButtomItems.Length > idx)
{
var barItem = rightButtomItems[idx];
if (barItem != null)
{
barItem.UpdateBadge(value, backgroundColor.ToUIColor(), textColor.ToUIColor());
}
}
});
}
}
}
Usage
void OnAttachClicked(object sender, EventArgs e)
{
//var answer = await DisplayAlert("Question?", "Would you like to play a game", "Yes", "No");
//Debug.WriteLine("Answer: " + answer);
ToolbarItem cmdItem = sender as ToolbarItem;
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, cmdItem, $"2", Color.DarkOrange, Color.White);
}
Links: 1) for instruction and 2) for sample code
https://www.xamboy.com/2018/03/08/adding-badge-to-toolbaritem-in-xamarin-forms/
https://github.com/CrossGeeks/ToolbarItemBadgeSample

Component One pdf generation using draw image crashing if printing pdf pages more than 40

I'm using below code to generate pdf of a page having listview. And it all works good till I have a very small list once I got list with more than 50 items it crashing with memory exception. I think variable pdf is taking all memory. I have checked using profiling it goes above 180 and pdf variable was on top when I took snapshot at profile.
async PDFTest_Loaded(int a)
{
try
{
pdf = new C1PdfDocument(PaperKind.Letter);
pdf.Compression = CompressionLevel.NoCompression;
WriteableBitmap writeableBmp = await initializeImage();
List<WriteableBitmap> ListBitmaps = new List<WriteableBitmap>();
pdfPage PageBitmaps = new pdfPage();
FrameworkElement header = RTABlock as FrameworkElement;
header.Arrange(pdf.PageRectangle);
var headerImage = await CreateBitmap(header);
FrameworkElement Pageheader = SalikPaymentReceipt as FrameworkElement;
Pageheader.Arrange(pdf.PageRectangle);
var PageHeaderImage = await CreateBitmap(Pageheader);
double pdfImageWidth = 0;
foreach (var item in EpayPreviewListView.Items)
{
List<WriteableBitmap> temp = new List<WriteableBitmap>();
var obj = EpayPreviewListView.ContainerFromItem(item);
List<FrameworkElement> controls = Children(obj);
StackPanel ListItemStackPanel = controls.Where(x => x is StackPanel && x.Name == "ListItemStackPanel").First() as StackPanel;
if (ListItemStackPanel is StackPanel)
{
StackPanel itemui = ListItemStackPanel as StackPanel;
if (!(pdfImageWidth > 0))
{
pdfImageWidth = itemui.ActualWidth;
}
itemui.Arrange(new Rect(0, 0, pdfImageWidth, pdf.PageRectangle.Height));
temp.Add(await CreateBitmap(itemui));
PageBitmaps = new pdfPage() { bitmap = temp };
CreateDocumentText(pdf, headerImage, writeableBmp, PageHeaderImage, PageBitmaps);
PageBitmaps = null;
temp = new List<WriteableBitmap>();
}
}
StorageFile Assets = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("Salik Payment Receipts.pdf", CreationCollisionOption.GenerateUniqueName);
PdfUtils.Save(pdf, Assets);
EpayPreviewListView.InvalidateArrange();
EpayPreviewListView.UpdateLayout();
LoadingProgress.Visibility = Visibility.Collapsed;
PrintButton.IsEnabled = true;
}
catch (Exception ex)
{
Debugger.Break();
}
}
public List<FrameworkElement> Children(DependencyObject parent)
{
try
{
var list = new List<FrameworkElement>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is StackPanel || child is TextBlock || child is ListView)
list.Add(child as FrameworkElement);
list.AddRange(Children(child));
}
return list;
}
catch (Exception e)
{
Debug.WriteLine(e.ToString() + "\n\n" + e.StackTrace);
Debugger.Break();
return null;
}
}
async public Task<WriteableBitmap> CreateBitmap(FrameworkElement element)
{
// render element to image (WinRT)
try
{
var renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(element);
var wb = new WriteableBitmap(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight);
(await renderTargetBitmap.GetPixelsAsync()).CopyTo(wb.PixelBuffer);
//var rect = new Rect(0, 0, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight);
if (!App.IsEnglishSelected)
{
wb = wb.Flip(WriteableBitmapExtensions.FlipMode.Vertical);
}
return wb;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString() + "\n\n" + ex.StackTrace);
Debugger.Break();
return new WriteableBitmap(0, 0);
}
}
bool isFirst = true;
void CreateDocumentText(C1PdfDocument pdf, WriteableBitmap headerImage, WriteableBitmap writeableBmp, WriteableBitmap pageHeading, pdfPage ListItem)
{
try
{
if (!isFirst)
{
pdf.NewPage();
}
isFirst = false;
pdf.Landscape = false;
double contentHeight = 0;
double leftMargin = 0;
string fontName = "Arial";
// measure and show some text
var text = App.GetResource("RoadandTransportAuthority");
var font = new Font(fontName, 36, PdfFontStyle.Bold);
// create StringFormat used to set text alignment and line spacing
var fmt = new StringFormat();
fmt.Alignment = HorizontalAlignment.Center;
var rc = new Rect(0, 0,
pdf.PageRectangle.Width, headerImage.PixelHeight);
pdf.DrawImage(headerImage, rc, ContentAlignment.MiddleCenter, Stretch.None);
contentHeight += headerImage.PixelHeight + 2;
rc = new Rect(0, contentHeight, pdf.PageRectangle.Width, writeableBmp.PixelHeight);
pdf.DrawImage(writeableBmp, rc);
contentHeight += writeableBmp.PixelHeight + 5;
rc = new Rect(leftMargin, contentHeight,
pdf.PageRectangle.Width,
pageHeading.PixelHeight);
pdf.DrawImage(pageHeading, rc, ContentAlignment.MiddleCenter, Stretch.None);
contentHeight += pageHeading.PixelHeight + 2;
Debug.WriteLine(ListItem.bitmap.Count.ToString());
for (int i = 0; i < ListItem.bitmap.Count; i++)
{
rc = PdfUtils.Offset(rc, 0, rc.Height + 10);
rc.Height = ListItem.bitmap.ElementAt(i).PixelHeight;
pdf.DrawImage(ListItem.bitmap.ElementAt(i), rc, ContentAlignment.TopCenter, Stretch.None);
ListItem.bitmap[i] = null;
}
ListItem = null;
}
catch (Exception e)
{
//...
}
}
It is due to memory clash I have to decrease the quality of images to handle it. Also it takes some time to release memory.

Not enough quota is available to process this command. (Exception from HRESULT: 0x80070718) in windows 8 metro app for GRID(Not for GRIDVIEW)

I am trying to generate dynamic controls in grid through UI where am dynamically specifying the size of controls. while generating more then 1500 control it is throwing this error "Not enough quota is available to process this command. (Exception from HRESULT: 0x80070718) " . i have seen some solution for gridview for the same exception but i am using GRID so not beneficial for me .
please let me know.
Thanks in advance.
<ScrollViewer HorizontalScrollMode="Auto"
HorizontalScrollBarVisibility="Auto"
VerticalScrollMode="Auto"
VerticalScrollBarVisibility="Auto" Margin="232,10,267,0" Grid.Row="1">
<Grid Name="dynamicgrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightBlue" Height="Auto" Width="Auto" Grid.Row="1"/>
</ScrollViewer>
C# code
try
{
MainPage mainpage = (MainPage)e.Parameter;
buttons = Convert.ToInt32(mainpage.buttonsize);
textblock = Convert.ToInt32(mainpage.txtBlocksize);
textbox = Convert.ToInt32(mainpage.txtBoxsize);
rows = Convert.ToInt32(mainpage.rows);
buttonwidth = Convert.ToInt32(mainpage.buttonwidth);
textblockwidth = Convert.ToInt32(mainpage.txtBlockwidth);
textboxwidth = Convert.ToInt32(mainpage.txtBoxwidth);
grdcolumn = buttons + textblock + textbox;
for (int i = 0; i < rows; i++)
{
RowDefinition rowDef = new RowDefinition();
rowDef.Height = new GridLength(200, GridUnitType.Auto);
dynamicgrid.RowDefinitions.Add(rowDef);
}
for (int j = 0; j < grdcolumn; j++) //need to mention
{
ColumnDefinition colDef1 = new ColumnDefinition();
colDef1.Width = new GridLength(100, GridUnitType.Auto);
dynamicgrid.ColumnDefinitions.Add(colDef1);
}
for (textboxcolumncount = 0; textboxcolumncount < textbox; textboxcolumncount++)
{
for (int i = 0; i < rows; i++)//textbox
{
TextBox txtbox = new TextBox();
txtbox.SetValue(TextBox.TextProperty, "txtbox" + i.ToString());
txtbox.Width = textboxwidth;
txtbox.Height = 50;
txtbox.SetValue(Grid.ColumnProperty, textboxcolumncount);
txtbox.SetValue(Grid.RowProperty, i);
dynamicgrid.Children.Add(txtbox);
dynamicgrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
}
}
textboxcolumncount = textbox;
for (textblockcolumncount = textboxcolumncount; textblockcolumncount < (grdcolumn - (buttons)); textblockcolumncount++)
{
for (int i = 0; i < rows; i++)
{
TextBlock txtblock = new TextBlock();
txtblock.SetValue(TextBlock.NameProperty, "txtblock" + i.ToString());
txtblock.Width = textblockwidth;
txtblock.Height = 50;
txtblock.SetValue(Grid.ColumnProperty, textblockcolumncount);
txtblock.SetValue(Grid.RowProperty, i);
txtblock.Text = "TextBlock" + i.ToString();
txtblock.Foreground = new SolidColorBrush(Colors.Black);
dynamicgrid.Children.Add(txtblock);
dynamicgrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
}
}
textboxcolumncount = textblockcolumncount;
for (buttonCoulmncount = textboxcolumncount; buttonCoulmncount < (grdcolumn); buttonCoulmncount++)
{
for (int i = 0; i < rows; i++) //button
{
Button btn = new Button();
btn.SetValue(Button.NameProperty, "btn" + i.ToString());
btn.Content = "Button" + i.ToString();
btn.Width = textboxwidth;
btn.Height = 50;
btn.Foreground = new SolidColorBrush(Colors.Black);
btn.SetValue(Grid.RowProperty, i);
btn.SetValue(Grid.ColumnProperty, buttonCoulmncount);
dynamicgrid.Children.Add(btn);
dynamicgrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
}
}
}
catch (Exception ex)
{
throw ex;
}
Go through this Link I am not sure wether this will solve your problem or you will have an idea of it.
Not enough quota ex
After that you can make a search. I still have not found any issue like this. Guess have to Replicate the code on the system. :)

WP7: LayoutTransform a ListBoxItem

Here's my XAML:
<ListBox x:Name="MyListBox" FontSize="40"
SelectionChanged="MyListBox_SelectionChanged">
</ListBox>
In this code-behind (below), I am attempting to animate a delete action. When the item is selected I delete it. I visually animate it with a ScaleTransform. In WPF I would use a LayoutTransform, but since I only have RenderTransform in WP/SL, I am using RenderTransform - and as a result the surrounding layout is not responding to the change in size. The record is still correctly deleted, but the visual effect is diminished.
Is there a way to do this in WP? Is there a way to resize a ListBoxItem so that the surrounding content responds?
ObservableCollection<string> m_Data;
public MainPage()
{
InitializeComponent();
m_Data = new ObservableCollection<string>
{ "One", "Two", "Three", "Four" };
MyListBox.ItemsSource = m_Data;
}
private void MyListBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
// fetch ListBoxItem
if (e.AddedItems.Count == 0)
return;
var _Data = e.AddedItems[0] as string;
var _Item = MyListBox.ItemContainerGenerator
.ContainerFromItem(_Data) as ListBoxItem;
// setup to resize using scale transform
var _Scale = new ScaleTransform
{
CenterX = _Item.RenderSize.Width / 2,
CenterY = _Item.RenderSize.Height / 2,
ScaleX = .99,
ScaleY = .99
};
_Item.RenderTransform = _Scale;
// setup storyboard
var _Story = new Storyboard();
_Story.Completed += (s, e1) =>
{
// remove data from collection
m_Data.Remove(_Data);
};
// animate scale X
var _AnimationX = new DoubleAnimation
{
To = .01,
Duration = TimeSpan.FromSeconds(2),
};
_Story.Children.Add(_AnimationX);
Storyboard.SetTarget(_AnimationX, _Scale);
Storyboard.SetTargetProperty(_AnimationX,
new PropertyPath(ScaleTransform.ScaleXProperty));
// animate scale Y
var _AnimationY = new DoubleAnimation
{
To = .01,
Duration = TimeSpan.FromSeconds(2),
};
_Story.Children.Add(_AnimationY);
Storyboard.SetTarget(_AnimationY, _Scale);
Storyboard.SetTargetProperty(_AnimationY,
new PropertyPath(ScaleTransform.ScaleYProperty));
_Story.Begin();
}
You can also use LayoutTransform on Windows Phone so I would just use that. .