Related
I have a code that should generate a Ranking of the players with the 3 highest scores and show it on the screen. I use Binding to take the elements of the list and generate an item for each player, with their email and score. However, I would like to know if there is any way to display only a part of the email, and not the complete one. For example: example.email#gmail.com, I would like to display only example.email, but I don't know if there is any way to edit the element that will go to the screen through SetBinding. The code that generates the Ranking is below:
List<UserRankingDTO> ranking = new UserQuestionHistoryService(StoreVarsHelper.UserToken).GetUsersRanking(3);
ListView listView = new ListView
{
Margin = 8,
ItemsSource = ranking,
ItemTemplate = new DataTemplate(() =>
{
Label nameLabel = new Label();
nameLabel.SetBinding(Label.TextProperty, "UserName");
nameLabel.TextColor = Color.White;
Label scoreLabel = new Label();
scoreLabel.SetBinding(Label.TextProperty, new Binding("UserScore", BindingMode.OneWay,
null, null, "Pontuação: {0:d}"));
scoreLabel.TextColor = Color.White;
return new ViewCell
{
View = new StackLayout
{
BackgroundColor = Color.FromHex("#2b2b80"),
Children =
{
new StackLayout
{
Spacing = 0,
Children =
{
nameLabel,
scoreLabel,
}
}
}
}
};
})
};
"Username" is the attribute of the UserRankingDTO class that has the email I would like to modify as stated above.
I've got a custom class for a button with a circular image as I'll be using it multiple times through my program. I thought it'd be pretty simple of creating class, inheriting from Button and slapping my setup into a constructor, but when I'm running the program the buttons are massive and plain (no image or text). Here's my class:
public class ImageButton : Button
{
public Button Button;
public ImageButton(string filename) : this(HorizontalAlignment.Center, VerticalAlignment.Center, filename)
{ }
public ImageButton(HorizontalAlignment hAlignment, VerticalAlignment vAlignment, string filename)
{
Button = new Button
{
Width = 35,
Height = 35,
Background = Brushes.Transparent,
HorizontalAlignment = hAlignment,
BorderBrush = Brushes.Transparent,
VerticalAlignment = vAlignment,
Content = new Image
{
Source = new BitmapImage(new Uri("pack://application:,,,/Resources/" + filename))
}
};
}
}
And here's my implementation of one of the instances
private void SetupHeaders(Grid resultGrid)
{
RowDefinition backbtn = new RowDefinition();
backbtn.Height = new GridLength(0.2, GridUnitType.Star);
resultGrid.RowDefinitions.Add(backbtn);
btn_Return = new ImageButton(HorizontalAlignment.Left, VerticalAlignment.Top, "returnicon.png");
Grid.SetRow(btn_Return, 0);
Grid.SetColumn(btn_Return, 0);
resultGrid.Children.Add(btn_Return);
}
with btn_Return being defined at the top of the class as simply
ImageButton btn_Return;
Here's an image of one of the buttons.
In you constructor you inititalize a Button with you properties and then assign it to a property. You never actually use the initialized button. You are always using ImageButton which is nothing more than an inherited button therefore you get the default behavior.
You have to change your constructor.
public ImageButton(HorizontalAlignment hAlignment, VerticalAlignment vAlignment, string filename)
{
Width = 35;
Height = 35;
Background = Brushes.Transparent;
HorizontalAlignment = hAlignment;
BorderBrush = Brushes.Transparent;
VerticalAlignment = vAlignment;
Content = new Image
{
Source = new BitmapImage(new Uri("pack://application:,,,/Resources/" + filename))
};
}
My aim is to create a .dll file dynamically having TextBox,Button which can be used by anyone in a program using Visual C#.
It would get created in Class Library, No WFA tools would get used.
I need help in creating a form which can generate multiple TextBox according to the attributes provided by the user.
1)No of TextBox
2)Location
3)Size etc
Code
CLASS.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace Forms
{
public class TextForm : Form
{
public TextBox txtBox1;
public TextForm(int a, int b, int c, int d, string e)
{
Form f1 = new Form();
txtBox1 = new TextBox();
txtBox1.Visible = true;
//f1.ActiveControl=txtBox1;
f1.Controls.Add(txtBox1);
txtBox1.Focus();
f1.Visible = true;
txtBox1.Size = new Size(a, b);
txtBox1.Location = new Point(c, d);
txtBox1.Text = (e).ToString();
this.Controls.Add(txtBox1);
txtBox1.Visible = true;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
}
}}
PROGRAM.CS
using System;
using Forms;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TextForm Box1 = (new TextForm(150, 14, 20, 32, "This is a TextBox 1"));
TextForm Box2 = (new TextForm(180, 34, 40, 52, "This is a TextBox 2"));
}}}
What should be the code?
The problem is that you are creating a Form for each TextBox. This is not what you want, provided that you plan to have forms with multiple text boxes.
I see two possibilities: you either want to create a) a textbox that you can easily add to your form, or b) a form with textboxes.
public class TextInput : Form
{
public TextBox TxtBox {
get; private set;
}
public Control Container {
get; private set;
}
public TextInput(Control c, int a, int b, int c, int d, string e)
{
this.Container = c;
this.TxtBox = new TextBox();
var txtBox1 = this.TxtBox;
txtBox1.Visible = true;
c.Controls.Add(txtBox1);
txtBox1.Focus();
txtBox1.Size = new Size(a, b);
txtBox1.Location = new Point(c, d);
txtBox1.Text = (e).ToString();
txtBox1.Visible = true;
}
}
You'd use this as follows:
var f = new Form();
var txtBox1 = new TextInput( f, 100, 25, 10, 10, "Name" );
var txtBox1 = new TextInput( f, 100, 25, 10, 50, "Age" );
var txtBox1 = new TextInput( f, 100, 25, 10, 100, "Address" );
var txtBox1 = new TextInput( f, 100, 25, 10, 150, "Phone" );
The second possibility is much more interesting, in my opinion. You want to create a special Form that automatically adds text boxes as soon a you call a simple method. I'm going to simplify your code, though. It is not a good idea (at all), to use absolute positioning in your forms.
The following creates a form with text boxes and their labels. The textboxes occupy the whole width of the form. This is achieved by using a TableLayoutPanel in which a Panel subPanel is used for each row.
This subPanel holds a label and a text box.
public class InputForm: Form {
public InputForm()
{
this.Panel = new TableLayoutPanel{ Dock = DockStyle.Fill };
this.textBoxes = new List<TextBox>();
this.Controls.Add( this.Panel );
}
public TextBox AddTextBox(string label)
{
var subPanel = new Panel { Dock = DockStyle.Top };
var lblLabel = new Label { Text = label, Dock = DockStyle.Left };
var tbEdit = new TextBox{ Dock = DockStyle.Fill };
subPanel.Controls.Add( tbEdit );
subPanel.Controls.Add( lblLabel );
this.Panel.Controls.Add( subPanel );
return tbEdit;
}
public TableLayoutPanel Panel {
get; private set;
}
public TextBox[] TextBoxes {
get {
return this.textBoxes.ToArray();
}
}
private List<TextBox> textBoxes;
}
You can use this with the following simple code:
var form = new InputForm();
var tbName = form.AddTextBox( "Name" );
var tbAge = form.AddTextBox( "Age" );
var tbAddress = form.AddTextBox( "Address" );
form.Show();
Application.Run( form );
If you'd like to give a few attributes to the text boxes to be created (colors, font, bold...), then you have two ways. The first one is to add parameters to the AddTextBox() method, though that would not scalate well as long as the number of attributes grows. The alternative is to create a TextBoxAttributes class, which will hold the configuring attributes for a given TextBox.
public class InputForm: Form {
public class TextBoxAttributes {
public TextBoxAttributes() {
this.ForeColor = DefaultForeColor;
this.BackColor = DefaultBackColor;
this.Font = DefaultFont;
}
public Color ForeColor {
get; set;
}
public Color BackColor {
get; set;
}
public Font Font {
get; set;
}
public bool Bold {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Bold;
}
this.Font = new Font( this.Font, style );
}
}
public bool Italic {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Italic;
}
this.Font = new Font( this.Font, style );
}
}
public bool Underline {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Underline;
}
this.Font = new Font( this.Font, style );
}
}
public float FontSize {
get {
return this.Font.Size;
}
set {
this.Font = new Font( this.Font.FontFamily, value );
}
}
}
// ... more things...
public TextBox AddTextBox(string label)
=> this.AddTextBox( label, new TextBoxAttributes() );
public TextBox AddTextBox(string label, TextBoxAttributes attr)
{
var subPanel = new Panel { Dock = DockStyle.Top };
var lblLabel = new Label { Text = label, Dock = DockStyle.Left };
var tbEdit = new TextBox{
Dock = DockStyle.Fill,
ForeColor = attr.ForeColor,
BackColor = attr.BackColor,
Font = attr.Font
};
subPanel.Controls.Add( tbEdit );
subPanel.Controls.Add( lblLabel );
this.Panel.Controls.Add( subPanel );
return tbEdit;
}
// ... more things...
}
The main code would be:
public static void Main()
{
var form = new InputForm();
var tbName = form.AddTextBox( "Name", new InputForm.TextBoxAttributes {
ForeColor = Color.Yellow,
BackColor = Color.Blue
});
var tbAge = form.AddTextBox( "Age", new InputForm.TextBoxAttributes {
ForeColor = Color.Green,
BackColor = Color.Black,
Bold = true
});
var tbAddress = form.AddTextBox( "Address" );
form.Show();
Application.Run( form );
}
Hope this helps.
If you are willing to switch to WPF this will become a lot easier, since you can profit from Autolayout and Bindings.
You could easily switch the Wrappanel for a StackPanel or a DockPanel.
The class will create a View based on the public properties of the handed over object. You might have to add additional Types to the Types-Dictionary. In my case those two where sufficient.
Create a Property of the DynamicControl and Bind to it in XAML.
XAML:
<ContentPresenter Content="{Binding Path=DynView}" />
public ViewModel
{
public UserControl DynView {get; private set};
private ModelType _model;
public ViewModel(ModelType model)
{
_model = model;
DynView = new DynamicControl<ModelType>(_model);
}
}
public class DynamicControl<T> : UserControl
{
static DynamicControl()
{
Types[typeof(bool)] = (binding) =>
{
CheckBox cb = new CheckBox();
cb.SetBinding(CheckBox.IsCheckedProperty,binding);
return cb;
};
Types[typeof(String)] = (binding) =>
{
TextBox tb = new TextBox();
tb.SetBinding(TextBox.TextProperty, binding);
return tb;
};
// add additional Types if necessary
}
private T _model;
public DynamicControl(T model)
{
_model = model;
WrapPanel wp = new WrapPanel();
foreach (PropertyInfo pi in model.GetType().GetProperties())
{
Grid g = new Grid();
g.Margin = new Thickness(5, 5, 25, 5);
g.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
g.ColumnDefinitions.Add(new ColumnDefinition());
g.ColumnDefinitions.Add(new ColumnDefinition());
g.RowDefinitions.Add(new RowDefinition());
TextBlock tb = new TextBlock() { Text = pi.Name };
tb.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumn(tb, 0);
Grid.SetRow(tb, 0);
g.Children.Add(tb);
System.Windows.FrameworkElement uie = GetUiElement(pi);
uie.Margin = new Thickness(10, 0, 0, 0);
uie.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumn(uie, 1);
Grid.SetRow(uie, 0);
g.Children.Add(uie);
wp.Children.Add(g);
}
this.Content = wp;
}
private FrameworkElement GetUiElement(PropertyInfo pi)
{
System.Windows.Data.Binding binding = new System.Windows.Data.Binding(pi.Name);
binding.Source = _model;
Func<System.Windows.Data.Binding, FrameworkElement> func;
FrameworkElement uie = null;
if (Types.TryGetValue(pi.PropertyType, out func))
uie = func(binding);
else
uie = Types[typeof(String)](binding);
return uie;
}
private static Dictionary<Type, Func<System.Windows.Data.Binding, FrameworkElement>> Types = new Dictionary<Type, Func<System.Windows.Data.Binding, FrameworkElement>>();
}
I think you're going at this all wrong. Just define your dimensions and text in advance, put them in a data class, and then feed a list of those data classes to your form constructor so it can construct them all on the fly.
The data class:
public class TextboxInfo
{
public Int32 Width { get; set; }
public Int32 Height { get; set; }
public Int32 X { get; set; }
public Int32 Y { get; set; }
public String Text { get; set; }
public TextboxInfo(Int32 w, Int32 h, Int32 x, Int32 y, String text)
{
this.Width = w;
this.Height = h
this.X = x;
this.Y = y
this.Text = text;
}
}
The code to construct the form:
public class TextForm : Form
{
public TextBox[] TextBoxes
{
get { return _textBoxes.ToArray(); }
}
private List<TextBox> _textBoxes;
public TextForm(TextboxInfo[] textboxes, Int32 padX, Int32 padY)
{
_textBoxes = new List<TextBox>();
Int32 reqWidth = 0;
Int32 reqHeight = 0;
foreach (TextboxInfo tbi in textboxes)
{
reqWidth = Math.Max(reqWidth, tbi.X + tbi.Width);
reqHeight = Math.Max(reqHeight, tbi.Y + tbi.Height);
TextBox txtB = new TextBox();
txtB.Size = new Size(tbi.Width, tbi.Height);
txtB.Location = new Point(tbi.X, tbi.Y);
txtB.Text = tbi.Text;
_textBoxes.Add(txtB);
this.Controls.Add(txtB);
}
// You may want to add some kind of OK button at the end here (based on reqHeight)
// and link that to a click listener that closes the form.
// Don't forget to adjust your reqHeight to the added height of that button!
// ...
// Set form to the minimum needed size according to its elements.
this.Size = new Size(reqWidth + padX, reqHeight + padY);
}
}
The calling code:
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TextboxInfo[] info = new TextboxInfo[2];
info[0] = new TextboxInfo(150, 14, 20, 32, "This is a TextBox 1");
info[1] = new TextboxInfo(180, 34, 40, 52, "This is a TextBox 2");
TextForm frm = new TextForm(info, 20, 32);
frm.ShowDialog();
// Now you can access the form's text box values through frm.TextBoxes[i].Text
}
}
Mind you, this whole system may seem useful at first, but consider that none of the text boxes have labels on them. Just starting values.
I've made systems for custom data before in a project I created, to generate a custom save options dialog depending on the chosen file type to save to, since each file type needed specific options.
Realistically, you'd create a form with some kind of description at the top and an OK and a Cancel button at the bottom, with a panel in between which has its vertical scrollbar set to enable-when-needed. Then you can dynamically put different custom controls in there to support different data types, like say, a checkbox, a text field, a numeric field, et cetera. They'll automatically be listed vertically in the list simply by keeping track of each control's height to get the next control's Y-offset, and if they'd exceed the form size the panel will make sure you can scroll down.
All you'd give to the form are objects of a data class like the one I showed, but without positioning data. They'd have a type, to figure out what kind of custom control to create, a description text, a default value to set the input control to, and possibly some kind of initialisation value, for example, to limit the range of a numeric value, or, as in the image I showed, values for a dropdown list.
I am trying to add a click event to a button that is defined in a different class.
Just a quick overview, this code creates a stack of cards with buttons on them and the buttons need click events.
The CardView class:
public class CardView : ContentView
{
public Label Name { get; set; }
public Image Photo { get; set; }
public Label Location { get; set; }
public Label Description { get; set; }
public Button PassButton { get; set; }
public Button FailButton { get; set; }
public CardView()
{
// gives the card its black line
Grid grid = new Grid();
grid.BackgroundColor = Color.Black;
grid.Padding = 2;
RelativeLayout view = new RelativeLayout();
// box view as the background
BoxView boxView1 = new BoxView
{
Color = Color.White,
InputTransparent = true
};
view.Children.Add(boxView1,
Constraint.Constant(0), Constraint.Constant(0),
Constraint.RelativeToParent((parent) => {
return parent.Width;
}),
Constraint.RelativeToParent((parent) => {
return parent.Height;
})
);
// items image
Photo = new Image()
{
InputTransparent = true,
Aspect = Aspect.Fill
};
view.Children.Add(Photo,
Constraint.Constant(0),
Constraint.RelativeToParent((parent) =>
{
double h = parent.Height * 0.80;
return ((parent.Height - h) / 2) + 20;
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
Constraint.RelativeToParent((parent) =>
{
return (parent.Height * 0.40);
})
);
// items label
Name = new Label()
{
TextColor = Color.Black,
FontSize = 22,
InputTransparent = true,
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.CenterAndExpand,
HorizontalTextAlignment = TextAlignment.Center
};
view.Children.Add(Name,
Constraint.Constant(10), Constraint.Constant(10),
Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
Constraint.Constant(28)
);
// location description
Location = new Label()
{
TextColor = Color.Black,
FontSize = 18,
InputTransparent = true
};
view.Children.Add(Location,
Constraint.Constant(30), Constraint.Constant(40),
Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
Constraint.Constant(28)
);
//Image[] stars = new Image[5];
StackLayout stack = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Spacing = 2
};
view.Children.Add(stack,
Constraint.RelativeToParent((parent) =>
{
return parent.Width - 90; //
}),
Constraint.Constant(40)); //40
// bottom label
Description = new Label()
{
TextColor = Color.Black,
FontSize = 16,
FontAttributes = FontAttributes.None,
HorizontalOptions = LayoutOptions.CenterAndExpand,
HorizontalTextAlignment = TextAlignment.Center,
InputTransparent = true
};
view.Children.Add(
Description,
Constraint.Constant(0),
Constraint.RelativeToParent((parent) =>
{
return (parent.Height / 2f) + 30;
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
Constraint.Constant(40)
);
// camera button
Button camera = new Button()
{
Text = "Camera",
InputTransparent = true
};
view.Children.Add(camera,
Constraint.RelativeToParent((parent) =>
{
return (parent.Width / 2f) - (camera.Width / 2f);
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height - 70;
})
);
PassButton = new Button()
{
Text = "Pass",
};
view.Children.Add(PassButton,Constraint.RelativeToParent((parent)=>
{
return (parent.Width / 8f) - (PassButton.Width / 4f);
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height - 70;
})
);
FailButton = new Button()
{
Text = "Fail",
};
view.Children.Add(FailButton, Constraint.RelativeToParent((parent) =>
{
return (parent.Width *(3/ 4f)) - (FailButton.Width / 4f);
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height - 70;
})
);
grid.Children.Add(view);
Content = grid;
}
}
This class is used as sort of a template for the entire deck.
In another class multiple instances of the CardView class are created to make the deck of cards.
The creation of the cards is working fine.
So in the CardStackView (in the constructor) the deck is created:
public CardStackView()
{
RelativeLayout view = new RelativeLayout();
// create a stack of cards
for (int i = 0; i < NumCards; i++) //
{
var card = new CardView();
cards[i] = card;
card.InputTransparent = true;
card.IsVisible = false;
view.Children.Add(
card,
Constraint.Constant(0),
Constraint.Constant(0),
Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height;
})
);
}
this.BackgroundColor = Color.Azure;
this.Content = view;
}
Is it possible to add click events/tapgestures to the buttons in the CardView class (PassButton and FailButton) in the constructor of the CardStackView when the deck is being created?
They kind of need to be added here given the nature of the rest of the CardStackView. There is a lot going on and its not feasible to reorganise the code at this point.
Is it even possible to do this?
Also things I have tried.
I tried using the instance of the CardView in the for loop to access the button and add the events but this simply did nothing.
i.e card.PassButton.Clicked += clickEvent.
Any ideas? Or even if it is possible?
Here we go.
I think that buttons, labels and image inside the CardView can be private variables, so you can deal with it in a more controlled way (the outside class should not change the position of the button inside your card, for example)
There's a lot of ways to do that. I thought 2 ways given your code structure:
- 1 Encapsulating the event handler definition
You can create a method in your CardView like:
public class CardView : ContentView
{
// Your stuffs
public void AddPassButtonClickedEvent(EventHandler handler)
{
if(handler != null)
PassButton.Clicked += handler;
}
// Your stuffs
}
Outside the class, you will use it like:
var cardView = new CardView();
cardView.AddPassButtonClickedEvent((sender, args) =>
{
// Do something
});
- 2 Exposing your own event
You can create your own events (or commands) at the CardView class and always asign the clicked event of the button. Like this:
public class CardView : ContentView
{
// Your stuffs
public event EventHandler MyPassButtonClickedEvent;
public CardView()
{
// Instantiate your PassButton
PassButton.Clicked += OnPassButtonClicked;
}
protected void OnPassButtonClicked(object sender, EventArgs args)
{
MyPassButtonClickedEvent?.Invoke(object, args);
}
// Your stuffs
}
Again, you can use it outside this way:
class Fake
{
CardView cardView;
public Fake()
{
cardView = new CardView();
cardView.MyPassButtonClickedEvent += MyHandler;
}
void MyHandler(object sender, EventArgus args)
{
// Do something
}
}
I know this question has been asked a lot but I've tried the various solutions and can't seem to find one that works. I have a label on my storyboard titled Messages. On button click, different text appears in the label. I need to pad just this label.
I've looked at:
Adding space/padding to a UILabel,
UILabel text margin,
and Resizing a UILabel to accommodate insets.
Also not sure where in my ViewController.cs to put the code. I put it under public partial class ViewController : UIViewController but get errors.
Edit 2:
Okay, at first I did a UITextView but couldn't get vertical align to work so went back to label. This is what I have:
public partial class ViewController : UIViewController
{
public partial class PaddedUILabel : UILabel
{
private UIEdgeInsets EdgeInsets { get; set; }
public PaddedUILabel()
{
EdgeInsets = new UIEdgeInsets(0, 10, 0, 10);
}
public override void DrawText(CoreGraphics.CGRect rect)
{
base.DrawText(EdgeInsets.InsetRect(rect));
}
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
Message.Layer.BorderWidth = 1;
Message.BackgroundColor = UIColor.FromWhiteAlpha(1, 0.88f);
PaddedUILabel _paddedUILabel = Message as PaddedUILabel;
I'm still not getting any padding.
You can either use a UITextView and provide the insets directly (as mentioned in this link) which you can do either in ViewDidLoad or ViewWillAppear, or you can subclass your UILabel and override the DrawText method.
The DrawText method helps manipulate the rectangle in which the text within a label is drawn. I'd suggest you pay around with some values to get started with it.
Something like:
public partial class PaddedUILabel : UILabel
{
//Override draw text here
}
If you are using Xamarin iOS Native, give your label(for example: myLabel) the custom class from story board and retrieve the label as:
PaddedUILabel _paddedUILabel = this.myLabel as PaddedUILabel;
I'm sorry I would have given you the whole code but as of now, don't have access to a Mac environment. Let me know if you need anything else.
For vertical align in TextView follow link.
Cheers
i tried many solutions as discussed here but the actual out coming not what i wanted so i made it like that :
if (this.Padding != default(Thickness))
{
Device.BeginInvokeOnMainThread(() =>
{
if (Parent is Grid)
{
var parentAsGrid = Parent as Grid;
var index = parentAsGrid.Children.IndexOf(this);
parentAsGrid.Children.Remove(this);
Grid marginGrid = new Grid() { BackgroundColor = this.BackgroundColor, HorizontalOptions = this.HorizontalOptions, VerticalOptions = this.VerticalOptions };
var lbl = new Label() { Text = this.Text, TextColor = this.TextColor, BackgroundColor = this.BackgroundColor, HorizontalOptions = this.HorizontalOptions, VerticalOptions = this.VerticalOptions, FontSize = this.FontSize };
lbl.Margin = this.Padding;
if (!parentAsGrid.Children.Contains(this))
{
marginGrid.Children.Add(lbl);
parentAsGrid.Children.Insert(index, marginGrid);
}
}
if (Parent is StackLayout)
{
var parentAsGrid = Parent as StackLayout;
var index = parentAsGrid.Children.IndexOf(this);
parentAsGrid.Children.Remove(this);
Grid marginGrid = new Grid() { BackgroundColor = this.BackgroundColor, HorizontalOptions = this.HorizontalOptions, VerticalOptions = this.VerticalOptions };
var lbl = new Label() { Text = this.Text, TextColor = this.TextColor, BackgroundColor = this.BackgroundColor, HorizontalOptions = this.HorizontalOptions, VerticalOptions = this.VerticalOptions, FontSize = this.FontSize };
lbl.Margin = this.Padding;
if (!parentAsGrid.Children.Contains(this))
{
marginGrid.Children.Add(lbl);
parentAsGrid.Children.Insert(index, marginGrid);
}
}
});