Reputation: 4487
I have a simple custom control, which I use in a ContentPage
(actually a LoginPage) in my Xamarin forms app. The custom control has a property called EntryText
which I am trying to bind to the LoginViewModel
's Email
property.
If I bind Email
with the custom control's EntryText
, it does not seem to work. However, if I bind Email
to a normal control like Entry
's Text
, it does work correctly. What am I doing wrong here?
My custom control:
public class FlakeEntry2 : StackLayout
{
public Entry Entry;
public Label ErrorLabel;
public FlakeEntry2()
{
Entry = new Entry { };
Children.Add(Entry);
ErrorLabel = new Label
{
FontAttributes = FontAttributes.Italic,
TextColor = Color.Red,
};
Children.Add(ErrorLabel);
}
#region Text property which I am trying to bind
public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(
propertyName: nameof(EntryText),
returnType: typeof(string),
declaringType: typeof(FlakeEntry2),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: EntryTextPropertyChanged);
public string EntryText
{
get { return GetValue(EntryTextProperty)?.ToString(); }
set { SetValue(EntryTextProperty, value); }
}
private static void EntryTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (FlakeEntry2)bindable;
control.Entry.Text = newValue?.ToString();
}
#endregion
}
The View (LoginPage) where I try to bind looks like this:
<StackLayout Orientation="Vertical" Spacing="10">
<custom:FlakeEntry2 x:Name="Email" EntryText="{Binding Email}" /> <!--This does not work-->
<Entry Text="{Binding Email}"/> <!--This works-->
</StackLayout>
Finally the ViewModel is pretty much standard and implements INotifyPropertyChanged
. The Email
property of which looks like:
private string _email;
public string Email
{
get { return _email; }
set
{
_email = value;
NotifyPropertyChanged();
}
}
I have tried adding a XAML based custom control (current one is just C# based).
I have tried explicitly adding BindingContext={Binding}
to the custom control used in the LoginPage
.
I have read numerous blogs but to no avail. Can someone please point me in the right direction?
Upvotes: 0
Views: 1156
Reputation: 5313
I've heard there are some things a bit different between the WPF and XF bindings and even its XAML syntaxes but I don't know much about WPF.
Whatever.
How about to use cascade bindings and take control of your component avoiding exposing its inner views?
I always use this approach and works pretty fine for me, see if it fit's to you too:
public class FlakeEntry2 : StackLayout
{
private Entry Entry;
private Label ErrorLabel;
public FlakeEntry2()
{
Entry = new Entry { };
ErrorLabel = new Label
{
FontAttributes = FontAttributes.Italic,
TextColor = Color.Red,
};
this.Entry.SetBinding(Entry.TextProperty, new Binding(nameof(EntryText), source: this));
// You'll need to do the same to label's and other properties you need expose, but you get rid of the 'OnChanged' methods
Children.Add(Entry);
Children.Add(ErrorLabel);
}
#region Text property which I am trying to bind
public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(
propertyName: nameof(EntryText),
returnType: typeof(string),
declaringType: typeof(FlakeEntry2),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay);
public string EntryText
{
get { return GetValue(EntryTextProperty)?.ToString(); }
set { SetValue(EntryTextProperty, value); }
}
#endregion
}
Nothing on your XAML nor VM should be changed.
Upvotes: 4