Could not change the property value dynamically in button click - xamarin.forms

I have created bindable property called Text in TargetClass.cs. That Text property is nested bindable property.
TargetClass.cs :
public class TargetClass : BindableObject
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create("Text", typeof(string), typeof(TargetClass), "Default", BindingMode.TwoWay, null,
OnTextChanged);
private static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
{
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
}
ViewModel.cs :
public class ViewModel : INotifyPropertyChanged
{
private string m_text = "New Value";
public string TextValue
{
get { return m_text; }
set
{
m_text = value;
OnPropertyChanged("TextValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then I have created MyView.cs
public class MyView : ContentView
{
private TargetClass target;
Label label;
public TargetClass Target
{
get
{
return target;
}
set
{
target = value;
label.Text = target.Text;
}
}
public MyView()
{
label = new Label();
label.FontSize = 50;
Content = label;
}
}
MainPage.xaml :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:BindingDemo"
x:Class="BindingDemo.MainPage">
<StackLayout>
<local:MyView >
<local:MyView.Target>
<local:TargetClass Text="{Binding TextValue}" >
<local:TargetClass.BindingContext>
<local:ViewModel />
</local:TargetClass.BindingContext>
</local:TargetClass>
</local:MyView.Target>
</local:MyView>
<Button Text="Click" Clicked="Button_Clicked" />
</StackLayout>
MainPage.xaml.cs:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
(BindingContext as ViewModel).TextValue = "Latest Value";
}
}
TextValue property is binded with Text bindble property.
I have changed value of TextValue property in button click in MainPage.xaml.cs.
If I click the button. it should show Latest value. But it shows new value,it did not changed from new value to latest value.
Is it possible to change the value of TextValue property in Button click dynamically ?

If you want to use the method above,you could check below (But it's not recommended.If TargetClass is not used anywhere else, this class seems redundant, you can add a BindableProperty to MyView directly):
in TargetClass.cs:
public class TargetClass : BindableObject
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create("Text", typeof(string), typeof(TargetClass), "Default", BindingMode.TwoWay, propertyChanged: OnTextChanged);
private static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
{
((TargetClass)bindable).View.label.Text = (string)newValue;
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public static readonly BindableProperty ViewProperty =
BindableProperty.Create("View", typeof(MyView), typeof(TargetClass), null, BindingMode.TwoWay);
public MyView View
{
get
{
return (MyView)GetValue(ViewProperty);
}
set
{
SetValue(ViewProperty, value);
}
}
}
in the page.xaml:
<StackLayout >
<local:MyView x:Name="MyView">
<local:MyView.Target>
<local:TargetClass x:Name="MyClass" View="{Binding ., Source={x:Reference MyView}}" Text="{Binding TextValue}" >
<local:TargetClass.BindingContext>
<local:ViewModel />
</local:TargetClass.BindingContext>
</local:TargetClass>
</local:MyView.Target>
</local:MyView>
<Button Text="Click" Clicked="Button_Clicked" />
</StackLayout>
in page.xaml.cs:
private void Button_Clicked(object sender, EventArgs e)
{
(MyClass.BindingContext as ViewModel).TextValue = "Latest Value";
}

Related

How to access the BindingContext of custom control in Xamarin.Forms

I have a CollectionView with ItemsSource set to ObservableCollection of type Employee.
The ItemTemplate of the CollectionView is a CustomControl that has 1 BindableProperty of Type Employee
MainPage.xaml:
<CollectionView ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee}">
<CollectionView.ItemTemplate>
<DataTemplate>
<controls:CustomControl Employee="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The CustomControl has an image (checked image to indicate selection).
CustomControl.xaml:
<Frame HasShadow="True"
BackgroundColor="Blue">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}" />
<Image Source="check.png" />
</StackLayout>
</Frame>
CustomControl.xaml.cs:
public partial class CustomControl : ContentView
{
public CustomControl()
{
InitializeComponent();
}
public static BindableProperty EmployeeProperty = BindableProperty.Create(
propertyName: nameof(Employee),
returnType: typeof(Employee),
declaringType: typeof(CustomControl),
defaultValue: default(Employee),
defaultBindingMode: BindingMode.OneWay);
public Employee Employee
{
get
{
return (Employee)GetValue(EmployeeProperty);
}
set
{
SetValue(EmployeeProperty, value);
}
}
}
Model (Employee):
public class Employee: INotifyPropertyChanged
{
private int name;
public int Name
{
get
{
return name;
}
set
{
name = value;
OnPropertyChanged(nameof(Name));
}
}
private int isSelected;
public int IsSelected
{
get
{
return isSelected;
}
set
{
isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
#region PropertyChanged
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
I am trying to create simple animation (FadeIn/FadeOut) for the checked image in the CustomControl so when an item is selected the image will fade in, and when unselected it will fade out. I could use IsVisible and set it to true/false but that's ugly.
My idea was to listen to PropertyChanged event of the Employee (which supposed to be the context of my CustomControl), and when the property IsSelected is modified, I will start the animation to show/hide the image. something like this
public CustomControl()
{
InitializeComponent();
(this.BindingContext as Employee).PropertyChanged += CustomControl_PropertyChanged;
}
private void CustomControl_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Employee.IsSelected))
{
//do animation to show/hide image
}
}
But couldn't access the Context of my CustomControl!
When I declare the binding in MainPage.xaml I am passing a single Emplyee objet as BindingContext (that dot, right?):
<controls:CustomControl Employee="{Binding .}" />
but after the CustomControl is initializd, the BindingContext is still null!
public CustomControl()
{
InitializeComponent();
var context = this.BindingContext; //this is null
}
How can I observe the changes on the IsSelected property of the Employee object from my CustomControl?
In your custom control override the OnBindingContextChanged method, inside of that method you should be able to access the binding context that is set for your view.
Ex:
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var context = this.BindingContext as Employee
}

Changing Property in code behind does not update view

When I change my property which is a model object, The view does not update unless I reassign the binding context. I am not using mvvm, so no view model.
public partial class MainPage : ContentPage
{
private MySource _myCurrentSource = new MySource("yolor");
public MySource MyCurrentSource {
get { return _myCurrentSource; }
set {_myCurrentSource = value; }
}
public MainPage()
{
InitializeComponent();
MyCurrentSource = _myCurrentSource;
MainStack.BindingContext = MyCurrentSource;
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
MyCurrentSource = new MySource("new string");
//property changed
MainStack.BindingContext = MyCurrentSource;
}
}
I want to get rid of : MainStack.BindingContext = MyCurrentSource;
This is what my xaml looks like
<?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="DataBindingPlayGround.MainPage">
<StackLayout Padding="10, 0" x:Name="MainStack" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label x:Name="label" Text="TEXT" FontSize="48" />
<Button Text="Change" Clicked="Button_Clicked"/>
</StackLayout>
</ContentPage>
Model class:
public class MySource
{
public MySource(string str)
{
SourceString = str;
}
public string SourceString { get; set; }
}
Modify MySource class as follows to have a try:
public class MySource : INotifyPropertyChanged
{
public MySource(string str)
{
sourceString = str;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string sourceString;
public double SourceString
{
set
{
if (sourceString != value)
{
sourceString = value;
OnPropertyChanged("SourceString");
}
}
get
{
return sourceString;
}
}
}
=============================Update=================================
Although not understanding the logic of your application, if you want to make MyCurrentSource works. You will also need to use INotifyPropertyChanged:
public partial class MainPage : ContentPage ,INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private MySource _myCurrentSource;
public MySource MyCurrentSource
{
set
{
if (_myCurrentSource != value)
{
_myCurrentSource = value;
OnPropertyChanged("MyCurrentSource");
}
}
get
{
return _myCurrentSource;
}
}
public MainPage()
{
InitializeComponent();
_myCurrentSource = new MySource("yolor");
//MyCurrentSource = _myCurrentSource;
MainStack.BindingContext = _myCurrentSource ;
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
_myCurrentSource = new MySource("new string");
//property changed
MainStack.BindingContext = _myCurrentSource;
}
}
Or you can directly set new Model when BindingContext.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
MainStack.BindingContext = new MySource("yolor");
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
//property changed
MainStack.BindingContext = new MySource("new string");
}
}
This is finally what worked for me, in case anyone has similar situation:
Source classes below:
public class FirstSource
{
public string sourceString;
public string SourceString { get; set; }
public int SourceOneProp2 { get; set; }
public FirstSource(string str, int num)
{
SourceString = str;
SourceOneProp2 = num;
}
}
public class SecondSource
{
public string ExampleField { get; set; }
public int SourceTwoProp2 { get; set; }
public SecondSource(string exampleField, int num)
{
ExampleField = exampleField;
SourceTwoProp2 = num;
}
}
ViewModel (Decided to use to make task easier)
class MainPageViewModel : BaseViewModel
{
private FirstSource _sourceOne;
private SecondSource _sourceTwo;
public FirstSource SourceOne
{
get { return _sourceOne; }
set { SetValue(ref _sourceOne, value); }
}
public SecondSource SourceTwo
{
get { return _sourceTwo; }
set { SetValue(ref _sourceTwo, value); }
}
}
Code Behind:
public partial class MainPage : ContentPage
{
int counter = 0;
private MainPageViewModel ViewModel
{
get { return BindingContext as MainPageViewModel; }
set { BindingContext = value; }
}
public MainPage()
{
InitializeComponent();
ViewModel = new MainPageViewModel();
ViewModel.SourceOne = new FirstSource("init1", 10);
ViewModel.SourceTwo = new SecondSource("init2", 20);
}
private void Button_Clicked(object sender, EventArgs e)
{
counter += 1;
ViewModel.SourceOne = new FirstSource("Changed1", 100+counter);
}
private void Button_Clicked_1(object sender, EventArgs e)
{
counter += 1;
ViewModel.SourceTwo = new SecondSource("Changed2", 200+counter);
}
}
XAML/UI
<StackLayout Padding="10, 0" x:Name="MainStack" HorizontalOptions="Center" VerticalOptions="Start">
<Label x:Name="label" Text="{Binding Path=SourceOne.SourceString}" FontSize="48" />
<Label Text="{Binding Path=SourceOne.SourceOneProp2}" />
<Button Text="Change" Clicked="Button_Clicked"/>
<StackLayout Padding="10, 0" x:Name="SecondStack">
<Label x:Name="secondLabel" Text="{Binding Path=SourceTwo.ExampleField}" FontSize="48" />
<Label Text="{Binding Path=SourceTwo.SourceTwoProp2}" />
<Button Text="Change" Clicked="Button_Clicked_1"/>
</StackLayout>
</StackLayout>

how to Add “View More” and view less at the end of label after 3 lines

I have label with 10 lines of data in it but need to show only 3 line after that need to add view more button and after expanding view less , how to add it in xamarin form
According to your description, you can use custom control to do this.
Firstly, you need to create contentview, name LargeTextLabel.xaml.
<ContentView.Content>
<StackLayout Orientation="Vertical">
<Label
x:Name="SmallLabel"
BackgroundColor="Beige"
HeightRequest="50"
IsVisible="true" />
<Label
x:Name="FullLabel"
BackgroundColor="BurlyWood"
HeightRequest="200"
IsVisible="false" />
<Button x:Name="ExpandContractButton" Text="See More" />
</StackLayout>
</ContentView.Content>
Then create BindableProperty by code behind.
public partial class LargeTextLabel : ContentView
{
public LargeTextLabel ()
{
InitializeComponent ();
}
public static readonly BindableProperty ExpandedProperty = BindableProperty.Create(
nameof(LargeTextLabel),
typeof(bool),
typeof(ContentView),
false,
BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
if (newValue != null && bindable is LargeTextLabel control)
{
var actualNewValue = (bool)newValue;
control.SmallLabel.IsVisible = !actualNewValue;
control.FullLabel.IsVisible = actualNewValue;
control.ExpandContractButton.Text = actualNewValue ? "See Less" : "See More";
}
});
public bool Expanded { get; set; }
public static readonly BindableProperty TextProperty = BindableProperty.Create(
nameof(LargeTextLabel),
typeof(string),
typeof(ContentView),
default(string),
BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
if (newValue != null && bindable is LargeTextLabel control)
{
var actualNewValue = (string)newValue;
control.SmallLabel.Text = actualNewValue;
control.FullLabel.Text = actualNewValue;
}
});
public string Text { get; set; }
public static readonly BindableProperty CommandProperty = BindableProperty.Create(
nameof(LargeTextLabel),
typeof(ICommand),
typeof(ContentView),
default(Command),
BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
if (newValue != null && bindable is LargeTextLabel control)
{
var actualNewValue = (ICommand)newValue;
control.ExpandContractButton.Command = actualNewValue;
}
});
public ICommand Command { get; set; }
}
Now, you can use this custom control in your page.
<ContentPage.Content>
<StackLayout>
<local:LargeTextLabel
Command="{Binding ExpandContractCommand}"
Expanded="{Binding TextExpanded}"
Text="{Binding LabelText}" />
</StackLayout>
</ContentPage.Content>
Create some property to bind this custom control, please implement INotifyPropertychanged to notify value update.
public partial class Page3 : ContentPage, INotifyPropertyChanged
{
private string _LabelText;
public string LabelText
{
get { return _LabelText; }
set
{
_LabelText = value;
RaisePropertyChanged("LabelText");
}
}
private ICommand _ExpandContractCommand;
private bool _TextExpanded;
public bool TextExpanded
{
get { return _TextExpanded; }
set
{
_TextExpanded = value;
RaisePropertyChanged("TextExpanded");
}
}
public Page3 ()
{
InitializeComponent ();
LabelText = "Can any one help me on this?\nI want set read more option for multiline text end of label when i click on that read more it will expand or navigate to the any other page. Please help me on this .\n\nThanks in advance.";
this.BindingContext = this;
}
public ICommand ExpandContractCommand
{
get
{
if (_ExpandContractCommand == null)
{
_ExpandContractCommand = new Command(() => {
TextExpanded = !TextExpanded;
});
}
return _ExpandContractCommand;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Xamarin Forms how to add behaviors to custom control

I have created a custom control,which is a ContentView with a Label and an Entry
The xaml of the custom controls looks like this:
<Label Text="{Binding Source={x:Reference ValidationControl}, Path=Caption}"/>
<Entry Text="{Binding Source={x:Reference ValidationControl}, Path=Value, Mode=TwoWay}" />
The code behind of the custom control looks like this:
public static readonly BindableProperty CaptionProperty = BindableProperty.Create(
nameof(Caption), typeof(string), typeof(ValidationEntry), default(string));
public string Caption
{
get => (string)GetValue(CaptionProperty);
set => SetValue(CaptionProperty, value);
}
public static readonly BindableProperty ValueProperty = BindableProperty.Create(
nameof(Value), typeof(string), typeof(ValidationEntry), default(string));
public string Value
{
get => (string)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
I’m using the custom control in the following way
<controls:ValidationEntry Caption=”Name:” Value="{Binding FullName, Mode=TwoWay}" />
My question is how to add behaviors to the custom control?
I would like to add them in the place that I’m using the control. i.e.
<controls:ValidationEntry Caption="Name:"
Value="{Binding FullName, Mode=TwoWay}">
<controls:ValidationEntry.EntryBehaviors>
<behaviors:EntryLengthValidatorBehavior IgnoreSpaces="True"/>
</controls:ValidationEntry.EntryBehaviors>
</controls:ValidationEntry>
You can create a behaviors directly, I add a NumericValidationBehavior in my custom entry to check the data if it is double.If type of the data is not double, the color of text will be set to red.
Here is xaml code.
<StackLayout>
<local:MyEntry local:NumericValidationBehavior.AttachBehavior="true">
</local:MyEntry>
</StackLayout>
Here is NumericValidationBehavior.cs
public static class NumericValidationBehavior
{
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached(
"AttachBehavior",
typeof(bool),
typeof(NumericValidationBehavior),
false,
propertyChanged: OnAttachBehaviorChanged);
public static bool GetAttachBehavior(BindableObject view)
{
return (bool)view.GetValue(AttachBehaviorProperty);
}
public static void SetAttachBehavior(BindableObject view, bool value)
{
view.SetValue(AttachBehaviorProperty, value);
}
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
{
var entry = view as Entry;
if (entry == null)
{
return;
}
bool attachBehavior = (bool)newValue;
if (attachBehavior)
{
entry.TextChanged += OnEntryTextChanged;
}
else
{
entry.TextChanged -= OnEntryTextChanged;
}
}
static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = double.TryParse(args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Color.Default : Color.Red;
}
}
Update
I create a custom view with ContentView
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BeHavDemo.MyView">
<ContentView.Content>
<StackLayout>
<Label Text="xxxx"/>
<Entry Text="eeeee" />
</StackLayout>
</ContentView.Content>
</ContentView>
Then I create a behavior.
public class MyBeha : Behavior<MyView>
{
protected override void OnAttachedTo(BindableObject view)
{
base.OnAttachedTo(view);
var myview=view as MyView;
StackLayout stackLayout = (StackLayout)myview.Content;
Label label = (Label)stackLayout.Children[0];
Entry entry=(Entry) stackLayout.Children[1];
}
}

UWP Custom renderer with Xamarin Forms

I have the following code for my custom renderer. The Element in use is a Label and I'm trying to set a background colour with rounded edges.
[assembly: ExportRenderer(typeof(RoundedLabel), typeof(RoundedLabelCustomRenderer))]
namespace MyNamespace.UWP.CustomRenderers
{
public class RoundedLabelCustomRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var view = (RoundedLabel)e.NewElement;
Children.Clear();
var border = new Border
{
CornerRadius = new CornerRadius(view.RoundedCornerRadius),
Background = new SolidColorBrush(view.RoundedBackgroundColor.ToWindows()),
Child = Control
};
Control.Padding = new Windows.UI.Xaml.Thickness(
view.InsidePadding.Left,
view.InsidePadding.Top,
view.InsidePadding.Right,
view.InsidePadding.Bottom);
Control.Foreground = new SolidColorBrush(view.TextColor.ToWindows());
Children.Add(border);
}
}
}
}
For the likes of a button (which is a composite object in UWP), this would be fine and if it was in "pure" XAML, something like
<Border background="gray" cornerradius="12">
<TextBlock />
</Border>
would do the job.
I'm just having fun and games trying to reconcile the two snippets together.
Any pointers to what I'm doing wrong would be appreciated.
It is difficult to realize your requirement with custom LabelRenderer. Because there is no such interface to modify background color and Radius. However, you can do that via custom View. And then in UWP client project you could use UserControl to render the control you want.
CustomNewLabelControl.cs
public class CustomNewLabelControl : View
{
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create(
propertyName: "LabelText",
eturnType: typeof(string),
declaringType: typeof(CustomNewLabelControl),
defaultValue: default(string));
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
public static readonly BindableProperty LabelRadiusProperty = BindableProperty.Create(
propertyName: "LabelRadius",
eturnType: typeof(double),
declaringType: typeof(CustomNewLabelControl),
defaultValue: default(double));
public double LabelRadius
{
get { return (double)GetValue(LabelRadiusProperty); }
set { SetValue(LabelRadiusProperty, value); }
}
public static readonly BindableProperty LabelBackgroundProperty = BindableProperty.Create(
propertyName: "LabelBackground",
eturnType: typeof(Color),
declaringType: typeof(CustomNewLabelControl),
defaultValue: default(Color));
public Color LabelBackground
{
get { return (Color)GetValue(LabelBackgroundProperty); }
set { SetValue(LabelBackgroundProperty, value); }
}
}
NewLabelControl.xaml.cs
public sealed partial class NewLabelControl : UserControl
{
public NewLabelControl()
{
this.InitializeComponent();
this.DataContext = this;
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(NewLabelControl), new PropertyMetadata(0));
public SolidColorBrush LabelBackground
{
get { return (SolidColorBrush)GetValue(LabelBackgroundProperty); }
set { SetValue(LabelBackgroundProperty, value); }
}
public static readonly DependencyProperty LabelBackgroundProperty =
DependencyProperty.Register("LabelBackground", typeof(SolidColorBrush), typeof(NewLabelControl), new PropertyMetadata(0));
public CornerRadius LabelRadius
{
get { return (CornerRadius)GetValue(LabelRadiusProperty); }
set { SetValue(LabelRadiusProperty, value); }
}
public static readonly DependencyProperty LabelRadiusProperty =
DependencyProperty.Register("LabelRadius", typeof(CornerRadius), typeof(NewLabelControl), new PropertyMetadata(0));
public SolidColorBrush LabelForeground
{
get { return (SolidColorBrush)GetValue(LabelForegroundProperty); }
set { SetValue(LabelForegroundProperty, value); }
}
public static readonly DependencyProperty LabelForegroundProperty =
DependencyProperty.Register("LabelForeground", typeof(SolidColorBrush), typeof(NewLabelControl), new PropertyMetadata(0));
}
NewLabelControl.xaml
<Grid>
<Border CornerRadius="{Binding LabelRadius}" Background="{Binding LabelBackground}">
<TextBlock Text="{Binding Text}" Foreground="{Binding LabelForeground }" />
</Border>
</Grid>
CustomNewLabelRanderer.cs
internal class CustomNewLabelRanderer : ViewRenderer<CustomNewLabelControl, NewLabelControl>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomNewLabelControl> e)
{
base.OnElementChanged(e);
if (Control == null)
{
SetNativeControl(new NewLabelControl());
}
if (e.OldElement != null)
{
}
if (e.NewElement != null)
{
Control.Text = Element.LabelText;
Control.LabelRadius = new Windows.UI.Xaml.CornerRadius(Element.LabelRadius);
Color color = Element.LabelBackground;
Control.LabelBackground = new Windows.UI.Xaml.Media.SolidColorBrush(
Windows.UI.Color.FromArgb(
(byte)(color.A * 255),
(byte)(color.R * 255),
(byte)(color.G * 255),
(byte)(color.B * 255)));
}
}
}
Usage
<local:CustomNewLabelControl LabelText="Welcome to Xamarin Forms!"
LabelBackground="Gray" LabelRadius="5"
VerticalOptions="Center"
HorizontalOptions="Center" />
What you're probably looking for is Frame (which actually is rendered as a Border on UWP). Frame let's you set both background color and corner radius:
<Frame BackgroundColor="Grey" CornerRadius="12" HasShadow="false" Padding="0">
<Label />
</Frame>
Frame has a drop shadow and padding set to 20 by default, so you'll have to removed those for your desired result.

Resources