Reputation: 1645
I have base custom control:
public class TabItem : ContentView
{
public TabItem()
{
SetBinding(HeaderProperty, new Binding("Header"));
}
public static readonly BindableProperty HeaderProperty =
BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string));
public string Header
{
get { return (string)GetValue(TabItem.HeaderProperty); }
set { SetValue(TabItem.HeaderProperty, value); }
}
}
I derive from this class and set Binding context:
public partial class FeedbackView : TabItem
{
public FeedbackView(FeedbackViewModel viewModel)
{
InitializeComponent();
Content.BindingContext = viewModel;
}
}
This is view model:
public class FeedbackViewModel : BaseViewModel
{
private string header;
public FeedbackViewModel()
{
Header = "Test Header";
}
public string Header
{
get { return header; }
set
{
header = value;
OnPropertyChanged("Header");
}
}
When I run it - header not binds to viewmodel's property. Is there something obvious that I forgot? Or I'm doing something wrong?
Upvotes: 3
Views: 6551
Reputation: 16222
As you do not share the XAML
part of FeedbackView
, one can only guess, but let's try nonetheless:
you say:
header not binds to viewmodel's property
I'm quite sure (from the code you've shared) the Header
property of TabItem
is set, even if your way of doing binding is unconventional. Is this the issue ? or your issue is that you don't have anything displayed on screen ?
Solving the "nothing displayed" issue require some changes to your code. First, set the propertyChanged
arg on BindableProperty.Create
public static readonly BindableProperty HeaderProperty =
BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string),
propertyChanged: OnHeaderChanged);
implements it, and create a virtual method so you can override it in your subviews
static void OnHeaderChanged (BindableObject bindable, object oldValue, object newvalue)
{
((TabItem)bindable).OnHeaderChanged ((string)oldValue, (string)newValue);
}
protected virtual void OnHeaderChanged (string oldValue, string newValue)
{
}
Now, in your derived FeedbackView
, you can override OnHeaderChanged
and set the label according to the Header
protected override void OnHeaderChanged (string oldValue, string newValue)
{
//headerLabel is defined in Xaml, and has a x:Name="headerLabel"
headerLabel.Text = newValue;
}
This should get you started.
As a last note, I'd say that setting the Binding in the TabItem
ctor is, well, unconventional. It breaks the MVVM pattern as the View (TabItem) makes some assumption about the structure of the ViewModel (and the existence of an Header property).
That binding is normally set on the TabItem inherited instance.
var feedback = new FeedbackView (myVm);
feedback.SetBinding (TabItem.HeaderProperty, "Header");
or, as passing the VM as ctor parameter already breaks MVVM, you could eventually do that in FeedbackView
ctor.
This last part is my humble opinion. Don't start a heated discussion about it, or do it without me involved :)
Upvotes: 1
Reputation: 45163
Your implementation of BindableProperty
is wrong. Look here how to do it right: https://blog.xamarin.com/using-custom-controls-in-xamarin.forms-on-android/
The Binding
to the property is usually done inside Page
. There you bind the property of your ViewModel
to the control's BindableProperty
. You don't do it inside the control itself.
Upvotes: 0