Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 91519

Custom Entry Renderer: Changing Property does not effect UI with MVVM

$
0
0

Hello guys,

I have a Custom Entry Renderer:
`
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Retailer.CustomControl
{
public class TextBox : Entry
{

    public static readonly BindableProperty BorderVisibilityProperty = BindableProperty.Create("BorderVisibility", typeof(bool), typeof(TextBox), false, BindingMode.TwoWay);

    public bool BorderVisibility
    {
        get
        {
            return (bool)GetValue(BorderVisibilityProperty);
        }
        set
        {
            SetValue(BorderVisibilityProperty, value);
        }
    }

    public new event EventHandler Completed;

    public void SendComplete()
    {
        Completed?.Invoke(this, EventArgs.Empty);
    }
}

}
`

in a rg.Xamarin.Pupup Page.

`
<?xml version="1.0" encoding="UTF-8"?>

<Grid VerticalOptions="Center" HorizontalOptions="Center">
    <ScrollView>
        <StackLayout VerticalOptions="Center" HorizontalOptions="Center" BackgroundColor="WhiteSmoke" Padding="16" WidthRequest="320">
            <StackLayout>
                <Label Text="No store information found!" FontSize="Medium" HorizontalOptions="Center" VerticalOptions="Center"/>
                <Label Text="Please insert this information about your store" FontSize="Body" HorizontalOptions="Center" VerticalOptions="Center"/>
            </StackLayout>

            <StackLayout>
                <Label Text="{Binding CountryTextBlockText}"/>
                <UserControl:TextBox Text="{Binding CountryTextBoxText}" />
            </StackLayout>

            <StackLayout>
                <Label Text="{Binding StreetTextBlockText}"/>
                <StackLayout Orientation="Horizontal">
                    <UserControl:TextBox Text="{Binding StreetTextBoxText}" />
                    <UserControl:TextBox Text="{Binding HouseNumberTextBoxText}"/>
                </StackLayout>
            </StackLayout>

            <StackLayout>
                <Label Text="{Binding PostalCodeTextBlock}"/>
                <UserControl:TextBox Placeholder="{Binding PostalCodeTextBoxText}" />
            </StackLayout>

            <StackLayout Orientation="Horizontal">
                <Label Text="{Binding MapVisibilityLabel}"/>
                <Switch IsToggled="{Binding ShowMapToggleToggled}"/>
            </StackLayout>

            <StackLayout Orientation="Horizontal">
                <Label Text="{Binding UseCurrentPositionButton}"/>
                <Button Text="{Binding UseCurrentPositionButtonText}" Command="{Binding GetCurrentPositionButtonCommand}"/>
            </StackLayout>

            <map:Map HeightRequest="240" IsVisible="{Binding ShowMapToggleToggled}"/>

            <Button Text="Submit" Command="{Binding SubmitButtonCommand}"/>
        </StackLayout>
    </ScrollView>
</Grid>


`

For UWP I created a Custom Renderer:

`
using Retailer.UWP.Renderer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ExportRenderer(typeof(Retailer.CustomControl.TextBox), typeof(TextBoxRenderer))]
namespace Retailer.UWP.Renderer
{
public class TextBoxRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);

        if (e.OldElement == null)
        {
            Control.BorderBrush = new SolidColorBrush();
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {

        if (((Retailer.CustomControl.TextBox)sender).BorderVisibility == false)
        {
            Control.BorderBrush = new SolidColorBrush();
        }

        if(e.PropertyName == nameof(TextBox.TextProperty))
        {
            if(Control.Text != (sender as Retailer.CustomControl.TextBox).Text)
                Control.Text = (sender as Retailer.CustomControl.TextBox).Text;
        }

    }

    private void FixFormsBackgroundColor(Xamarin.Forms.Frame frame)

    {

        var color = new Windows.UI.Color

        {

            A = Convert.ToByte(frame.BackgroundColor.A * 255),

            R = Convert.ToByte(frame.BackgroundColor.R * 255),

            G = Convert.ToByte(frame.BackgroundColor.G * 255),

            B = Convert.ToByte(frame.BackgroundColor.B * 255)

        };



        if (Control.Parent is Panel parent)

        {

            parent.Background = null;

        }



        Control.Background = new SolidColorBrush(color);

    }
}

}
`

For iOS:
`
using Retailer.CustomControl;
using Retailer.iOS.Renderer;
using System.ComponentModel;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(TextBox), typeof(TextFieldRenderer))]
namespace Retailer.iOS.Renderer
{
public class TextFieldRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);

        if (Control == null)
        {
            Control.BorderStyle = UITextBorderStyle.None;
            Control.BackgroundColor = UIColor.White;
        }


    }
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (Control != null && ((Retailer.CustomControl.TextBox)sender).BorderVisibility == false)
        {
            Control.BorderStyle = UITextBorderStyle.None;
        }
        else
        {
            Control.BorderStyle = UITextBorderStyle.Line;
        }
    }
}

}
`

And Android:

`
using Android.Content;
using Retailer.Droid.Renderer;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(Retailer.CustomControl.TextBox), typeof(CustomEntryRenderer))]
namespace Retailer.Droid.Renderer
{
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);

        if (Control != null)
        {
            Control.SetBackground(new Android.Graphics.Drawables.ColorDrawable(Android.Graphics.Color.White));
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (((Retailer.CustomControl.TextBox)sender).BorderVisibility == false)
        {

        }
    }
}

}
`

Changing the Properties in Constructure in ViewModel works to change the Value of myCustom Renderer TextBox. But I am trying to fill the TextBoxes with Lication Data from Geocoding.

` private string countryTextBoxText;

    public string CountryTextBoxText
    {
        get { return countryTextBoxText; }
        set { SetProperty(ref countryTextBoxText, value);
 }

`

`
private async Task setCurrentPlacemark()
{
var location = await Geolocation.GetLocationAsync();

        var placemarks = await Geocoding.GetPlacemarksAsync(location);

        currentPlacemark = placemarks?.FirstOrDefault();

        CountryTextBoxText = currentPlacemark.CountryName;

        if (placemarks != null)
        {
            PositionDataDownloaded();
        }

    }

`

But this does not work. Replacing TextBox with Entry works perfectly. I think my Custom renderer does sot support Binding the original Text Property. But Why?

Hopefully someone can help.


Viewing all articles
Browse latest Browse all 91519

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>