Change entry Border color using Custom Renderers in xamarin

Viewed 4496

I have used custom renderer class and i am able to change the border color. Now on click of a button i want to reset it again. I tried to reset it on click of a buttom but it's not working for both iOS and Android.

       .xaml file

       <local:BorderedEntryRenderer x:Name="NameEntry"
                     HorizontalOptions="EndAndExpand" VerticalOptions="Start"
                     WidthRequest="210"
                     Text="{Binding ProfileName}" BorderColor="Chocolate" />


       .cs file

         public void EditProfile_Clicked(System.Object sender, System.EventArgs e)
         {
            NameEntry.BorderColor = Color.Blue; //to reset the color on click
         }
2 Answers

Welcome to SO !

If want to use custom renderer for Entry in Xamarin Forms , you can have a look at this document first (https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/entry)

Here if need to change border color of Entry , actually need to use custom renderer to achieve that .

Create a custom Entry in Forms .

public class MyEntry : Entry
{
}

Used in Xaml :

<ContentPage ...
    xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
    ...>
    ...
    <local:MyEntry Text="In Shared Code" />
    ...
</ContentPage>

Then in iOS solution , need to create a renderer class(such as CustomEntryRenderer) :

[assembly: ExportRenderer(typeof(MyEntry), typeof(CustomEntryRenderer))]
namespace AppEntryTest.iOS
{
    public class CustomEntryRenderer : EntryRenderer,IUITextFieldDelegate
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            Control.Layer.BorderColor = UIColor.Red.CGColor;
            Control.Layer.BorderWidth = 1;
        }

    }
}

Also in Android solution , need to create a custom renderer class :

[assembly: ExportRenderer(typeof(MyEntry), typeof(CustomEntryRenderer))]
namespace AppEntryTest.Android{
public class CustomEntryRenderer : EntryRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement == null)
        {
            var nativeEditText = (global::Android.Widget.EditText)Control;
            var shape = new ShapeDrawable(new Android.Graphics.Drawables.Shapes.RectShape());
            shape.Paint.Color = Xamarin.Forms.Color.Red.ToAndroid();
            shape.Paint.SetStyle(Paint.Style.Stroke);
            nativeEditText.Background = shape;
        }
    }
}

The effect:

enter image description hereenter image description here

=============================Update===============================

If want to use event to control the border of Entry , we can use MessageCenter to achieve that .

For example , we can create two buttons in Xaml to add two clicked method to control the border of Entry .

<Button Text="SetBorder" Clicked="Button_Clicked_setborder"/>
<Button Text="Reset" Clicked="Button_Clicked_reset"/>

The implement of each clicked method is :

private void Button_Clicked_setborder(object sender, EventArgs e)
{
    MessagingCenter.Send<object,bool>(this,"Hi",true);
}

private void Button_Clicked_reset(object sender, EventArgs e)
{
    MessagingCenter.Send<object, bool>(this, "Hi", false);
}

Then in the iOS entry renderer class , modified as follow :

[assembly: ExportRenderer(typeof(MyEntry), typeof(CustomEntryRenderer))]
namespace AppEntryTest.iOS
{
    public class CustomEntryRenderer : EntryRenderer,IUITextFieldDelegate
    {

        CoreGraphics.CGColor defaultBorderColor;
        nfloat defaultBorderWidth;

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            defaultBorderColor = Control.Layer.BorderColor;
            defaultBorderWidth = Control.Layer.BorderWidth;


            MessagingCenter.Subscribe<object, bool>(this, "Hi", (sender, arg) =>
            {
                // Do something whenever the "Hi" message is received
                Console.WriteLine("Hi , I have received this");
                if (arg)
                {
                    Control.Layer.BorderColor = UIColor.Red.CGColor;
                    Control.Layer.BorderWidth = 1;
                }
                else
                {
                    Control.Layer.BorderColor = defaultBorderColor;
                    Control.Layer.BorderWidth = defaultBorderWidth;
                }

            });

          
        }

    }
}

The same modified in Android renderer class :

[assembly: ExportRenderer(typeof(MyEntry), typeof(CustomEntryRenderer))]
namespace AppEntryTest.Droid
{
    [Obsolete]
    public class CustomEntryRenderer : EntryRenderer
    {
        Drawable defaultTextBackgroundColor;
        public CustomEntryRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            
            defaultTextBackgroundColor = Control.Background;

            MessagingCenter.Subscribe<object,bool>(this, "Hi", (sender,arg) =>
            {
                // Do something whenever the "Hi" message is received
                Console.WriteLine("Hi , I have received this");
                if (arg)
                {
                    var shape = new ShapeDrawable(new Android.Graphics.Drawables.Shapes.RectShape());
                    shape.Paint.Color = Xamarin.Forms.Color.Red.ToAndroid();
                    shape.Paint.SetStyle(Paint.Style.Stroke);
                    Control.Background = shape;
                }
                else
                {
                    Control.Background = defaultTextBackgroundColor;
                }
           
            });

        }

    }
}

The effect :

iOS effect Android effect

I think you should checkout Xamarin Forms Triggers.

using triggers you will be able to fire up events from actions or states. It also helps u to keep everything organized in the xaml file without the need for the code behind.

Related