[FIXED] How to override default xamarin.forms.entry behavior

Issue

I need to make custom control for uwp project that derives from xamarin forms entry element.
The border of the control needs to remain red when hovering on it. But it sticks to its default behavior and changes border color on hover to gray.
I created the CypressEntry class, renderer for it, but it didn’t fix the issue.
I also tried to set the global style settings in app.xaml, specified the properties under all common visual states, still no luck.

Please help.

Code of entry class:

    {
        public static readonly BindableProperty BorderColorProperty =
      BindableProperty.Create(nameof(BorderColor),
          typeof(Color), typeof(CypressEntry), Color.Red);
        // Gets or sets BorderColor value  
        public Color BorderColor
        {
            get => (Color)GetValue(BorderColorProperty);
            set => SetValue(BorderColorProperty, value);
        }

        public static readonly BindableProperty BorderWidthProperty =
        BindableProperty.Create(nameof(BorderWidth), typeof(int),
            typeof(CypressEntry), Device.OnPlatform<int>(1, 2, 1));
        // Gets or sets BorderWidth value  
        public int BorderWidth
        {
            get => (int)GetValue(BorderWidthProperty);
            set => SetValue(BorderWidthProperty, 2);
        }
        public static readonly BindableProperty CornerRadiusProperty =
        BindableProperty.Create(nameof(CornerRadius),
            typeof(double), typeof(CypressEntry), Device.OnPlatform<double>(0, 0, 0));
        // Gets or sets CornerRadius value  
        public double CornerRadius
        {
            get => (double)GetValue(CornerRadiusProperty);
            set => SetValue(CornerRadiusProperty, value);
        }
        public static readonly BindableProperty IsCurvedCornersEnabledProperty =
        BindableProperty.Create(nameof(IsCurvedCornersEnabled),
            typeof(bool), typeof(CypressEntry), false);
        // Gets or sets IsCurvedCornersEnabled value  
        public bool IsCurvedCornersEnabled
        {
            get => (bool)GetValue(IsCurvedCornersEnabledProperty);
            set => SetValue(IsCurvedCornersEnabledProperty, value);
        }
    }

Code of renderer

[assembly: ExportRenderer(typeof(CypressEntry), typeof(CypressEntryRenderer))]
namespace Test.UWP.Renderers
{
    public class CypressEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            
            if (Element is CypressEntry view)
            {
                view.Unfocused += View_Unfocused;
                view.TextChanged += View_TextChanged;
            }

            if (Control is Windows.UI.Xaml.Controls.TextBox textBox)
            {
                
            }

            SetStyle();
        }


        private void View_TextChanged(object sender, TextChangedEventArgs e)
        {
            SetStyle();
        }

        private void View_Unfocused(object sender, FocusEventArgs e)
        {
            SetStyle();
        }

        private void SetStyle()
        {
            if (Element is CypressEntry view)
            {
                if (view.IsCurvedCornersEnabled)
                    Control.CornerRadius = new Windows.UI.Xaml.CornerRadius(view.CornerRadius);

                Control.BorderBrush = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Color.FromArgb(
                    (byte)(view.BorderColor.A * 255),
                    (byte)(view.BorderColor.R * 255),
                    (byte)(view.BorderColor.G * 255),
                    (byte)(view.BorderColor.B * 255)));

                Control.BorderThickness = new Windows.UI.Xaml.Thickness(view.BorderWidth);
            }
        }
    }
}

Also I tried to add visual state settings to xaml of the page that the control is used on:

<local:CypressEntry >
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <VisualState.Setters>
                                    <Setter Property="BorderColor" Value="Red" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Focused">
                                <VisualState.Setters>
                                    <Setter Property="BorderColor" Value="Red" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <VisualState.Setters>
                                    <Setter Property="BorderColor" Value="Red" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="PointerOver">
                                <VisualState.Setters>
                                    <Setter Property="BorderColor" Value="Red" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </local:CypressEntry>

Still the result is:

  1. When not hovered:

enter image description here

  1. When hovered:

enter image description here

Solution

How to override default xamarin.forms.entry behavior

It is UWP native FormsTextBox default behavir, the textbox will update border element with specific solidcolorbrush when pointover or focused.

The easy way copy FormsTextBoxStyle in UWP app.xaml file and override default pointover or focused SolidColorBrush to override default behavior.

Find above line 152 update Value as Red for focus status.

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
                                                </ObjectAnimationUsingKeyFrames>

Answered By – Nico Zhu

Answer Checked By – Marilyn (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published