3

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?

2
  • It seems that your forgot to implement INotifyPropertyChanged in FeedbackViewModel. Commented Aug 19, 2015 at 9:49
  • @Wosi Sorry, I forgot that my FeedbackViewModel derived from BaseViewModel class where INotifyPropertyChanged Already implemented. I edit code in question. Commented Aug 19, 2015 at 10:48

2 Answers 2

1

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 :)

Sign up to request clarification or add additional context in comments.

Comments

0

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.

2 Comments

Why I can't define binding inside control itself? I also update code in question. Is it correct now?
The control doesn't know anything about the ViewModel. The name of the bound property is not important to the BindableProperty. Otherwise TextView.TextProperty could only be bound to a property named text instead of binding it to CustomerViewModel.LastName or UserViewModel.EmailAddress. The binding is done in the Page or its XAML file. This is the connection between ViewModel and Control. So your implementation is still wrong. Read the blog entry and you'll see the difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.