2015-08-19 2 views
3

У меня есть базовый пользовательский элемент управления:Xamarin.Forms связывания с использованием SetBinding не работает

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); } 
    } 
} 

Я выводим из этого класса и установить Binding контекст:

public partial class FeedbackView : TabItem 
{ 
    public FeedbackView(FeedbackViewModel viewModel) 
    { 
     InitializeComponent();  
     Content.BindingContext = viewModel;  
    } 
} 

Это вид модели:

public class FeedbackViewModel : BaseViewModel 
{ 
    private string header; 

    public FeedbackViewModel() 
    { 
     Header = "Test Header"; 
    } 

    public string Header 
    { 
     get { return header; } 
     set 
     { 
      header = value; 
      OnPropertyChanged("Header"); 
     } 
     } 

Когда я запускаю его - заголовок не привязывается к свойству viewmodel. Есть ли что-то очевидное, что я забыл? Или я делаю что-то неправильно?

+0

Похоже, что вы забыли реализовать 'INotifyPropertyChanged' в' FeedbackViewModel'. – Wosi

+0

@Wosi Извините, я забыл, что мой 'FeedbackViewModel' получен из класса BaseViewModel, где уже реализовано' INotifyPropertyChanged'. Я редактирую код. –

ответ

0

Неверная реализация BindableProperty. Посмотрите, как это делается: https://blog.xamarin.com/using-custom-controls-in-xamarin.forms-on-android/

Binding к собственности, как правило, делается внутри Page. Там вы привязываете свойство своего ViewModel к элементу управления BindableProperty. Вы не делаете этого внутри самого элемента управления.

+0

Почему я не могу определить привязку внутри самого элемента управления? Я также обновляю код. Правильно ли сейчас? –

+0

Элемент управления ViewModel не знает ничего. Имя связанного свойства не важно для 'BindableProperty'. В противном случае 'TextView.TextProperty' может быть привязан только к свойству с именем' text' вместо привязки его к 'CustomerViewModel.LastName' или' UserViewModel.EmailAddress'. Связывание выполняется в файле 'Page' или' XAML'. Это связь между «ViewModel» и «Control». Таким образом, ваша реализация по-прежнему неправа. Прочтите запись в блоге, и вы увидите разницу. – Wosi

-1

Убедитесь, что BaseView наследует от

INotifyPropertyChanged, INotifyPropertyChanging

, а затем осуществлять следующее:

#region INotifyPropertyChanging implementation 
    public event PropertyChangingEventHandler PropertyChanging; 
    #endregion 

    public virtual void OnPropertyChanging(string propertyName) 
    { 
     if (PropertyChanging == null) 
      return; 

     PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); 
    } 


    #region INotifyPropertyChanged implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 

    public virtual void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged == null) 
      return; 

     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

Затем вы можете использовать привязки и получить событие изменения свойства

+0

'TabItem', BaseView, наследуется от' ContentView' и имеет встроенный INPC –

1

Поскольку вы не делите XAML часть FeedbackView, можно только догадываться, но давайте попробуем, тем не менее:

вы говорите:

заголовок не связывается собственности ViewModel в

Я совершенно уверен (из кода вы поделились) установлено значение Header объекта TabItem, даже если ваш способ привязки является нетрадиционным. Это проблема? или ваша проблема в том, что у вас ничего нет на экране?

Решение проблемы «ничего не отображается» требует внесения некоторых изменений в код. Во-первых, установите propertyChanged ARG на BindableProperty.Create

public static readonly BindableProperty HeaderProperty = 
    BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string), 
    propertyChanged: OnHeaderChanged); 

реализует его, и создать виртуальный метод, так что вы можете изменить его в своих подвидов

static void OnHeaderChanged (BindableObject bindable, object oldValue, object newvalue) 
{ 
    ((TabItem)bindable).OnHeaderChanged ((string)oldValue, (string)newValue); 
} 

protected virtual void OnHeaderChanged (string oldValue, string newValue) 
{ 
} 

Теперь, производный FeedbackView, вы можете переопределить OnHeaderChanged и установить метку в соответствии с Header

protected override void OnHeaderChanged (string oldValue, string newValue) 
{ 
    //headerLabel is defined in Xaml, and has a x:Name="headerLabel" 
    headerLabel.Text = newValue; 
} 

Это должно начать вас.

Как последнее примечание, я бы сказал, что установка привязки в TabItem ctor, ну, нетрадиционная.Он разбивает шаблон MVVM, поскольку представление (TabItem) делает некоторое предположение о структуре ViewModel (и о существовании свойства Header).

Эта привязка обычно устанавливается в унаследованном экземпляре TabItem.

var feedback = new FeedbackView (myVm); 
feedback.SetBinding (TabItem.HeaderProperty, "Header"); 

или, передавая в качестве параметра VM CT уже перерывам MVVM, в конечном итоге вы могли бы сделать это в FeedbackView CTOR.

Эта последняя часть - мое скромное мнение. Не начинайте жаркую дискуссию об этом или делайте это без меня.

Смежные вопросы