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.