Проблемы с привязками в формах Xamarin (MVVM) - PullRequest
0 голосов
/ 10 мая 2018

У меня проблемы с пониманием xaml с помощью mvvm.Иногда работает, но другие нет.

ViewModel (реализует INotifyPropertyChanged):

private Class1 firstClass;
public Class1 FirstClass{
    get{return firstClass;}
    set{firstClass = value; OnPropertyChanged();}
}

private string name;
public string Name{
    get{return name;}
    set{name = value; OnPropertyChanged();}
}

private string address;
public string Address{
    get{return address;}
    set{address = value; OnPropertyChanged();}
}

View:

private ViewModel vm;

В конструкторе View:

vm = new ViewModel(id);
BindingContext = vm;

OnAppearing (async):

base.OnAppearing();
await vm.LoadDataAsync();
lAddress.SetBinding(Label.TextProperty, new Binding("Address");
  • Если я устанавливаю BindingContext в xaml и удаляю его из конструктора, он не работает.

  • Если я установлю привязку на метку адреса в xaml и удалю ее из кода позади, она не будет работать.

  • Если япопробуйте использовать имя в качестве заголовка страницы, это не работает.

  • В любом из этих случаев я не получаю никакой ошибки, например «Binding: свойство не найдено в BindingContext», поэтому я понимаю, что они обнаруживаются, но, возможно, они пусты.

  • Если я изменю свойство из Class1, оно не появится на странице.Могу ли я предположить, что причина в том, что Class не реализует INotifyPropertyChanged?

  • Лучше или целесообразнее использовать LoadData в конструкторе VM (Task.Run) или в Page.OnAppearing (await vm.LoadData ())?

Может ли кто-нибудь дать совет?

РЕДАКТИРОВАТЬ:

XAML-код (извините, не удалось добавитьсам код)

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Если я устанавливаю BindingContext в xaml и удаляю его из конструктора, он не работает.

Как установить его в XAML?Вы должны предоставить int параметр конструктору.Поэтому, скорее всего, имеет смысл установить BindingContext страницы в C #:

class MyPage
{
    ViewModel vm;

    public MyPage(int id)
    {
        InitializeComponent();
        vm = new ViewModel(id);
        BindingContext = vm;
    }
}

Обратите внимание, что вы вводите здесь тесную связь, так как ваш Page знает о ViewModelконкретный тип.

Если я установлю привязку на метку адреса в xaml и удалю ее из кода позади, она не будет работать.

Вот как Label с переплетом должен выглядеть так: XAML:

<Label Text="{Binding Address}" />

Если я попытаюсь использовать Имя в качестве заголовка страницы, это не сработает.

Вот как создать привязку к заголовку страницы:

ContentPage.SetBinding(Page.TitleProperty, nameof(Class1.Name));

Обратите внимание, что она должна вызываться после установки BindingContext страницы.

Inни в одном из этих случаев я не получаю никакой ошибки, например «Binding: свойство не найдено в BindingContext», поэтому я понимаю, что они обнаруживаются, но, возможно, они пусты.

Попробуйте установить точку останова послеvm.LoadDataAsync() и проверьте содержимое ViewModel.

Если я изменю свойство из Class1, ононе появляется на странице.Могу ли я предположить, что причина в том, что Class не реализует INotifyPropertyChanged?

Чем больше я слежу за вашими вопросами, тем больше похоже на проблему реализации INotifyPtopertyChanged Можете ли вы поделиться соответствующим кодом?

Лучше или целесообразнее загружать данные в конструктор виртуальной машины (Task.Run) или в Page.OnAppearing (await vm.LoadData ())?

Конструктор должен иметь виднастолько просто, насколько это возможно, никогда не создавайте пользовательские конструкторы для выполнения кода, который может не работать, как правило.Поэтому лучше представить интерфейс, который будет реализован вашим ViewModel и который должен иметь методы OnAppearing() & OnDisappearing(), тогда ваша страница не будет знать о конкретном типе ViewModel.Я думаю, остальное должно быть ясно.

0 голосов
/ 10 мая 2018

Это довольно трудоемкая отладка (и причина, почему один вопрос на пост может иметь больше смысла); но здесь идет:

  1. В вашей модели представления есть конструктор, который принимает параметр. Если вы создаете в XAML, он будет использовать значение по умолчанию. По сути, два кода, которые вы сравниваете, не эквивалентны. Если вам нужен параметр, сохраните его так, как он есть у вас.

  2. Вам нужно будет отладить этот; убедитесь, что связанное свойство не является пустым для начинающих.

  3. Понятия не имею; такой же, как адрес, который вам, вероятно, понадобится для его отладки.

  4. Ваша интерпретация этого правильна; Я бы проверил, что мои данные загружены правильно.

  5. Да. Ваш текущий код будет обновляться только в случае переназначения FirstClass. Чтобы поймать присвоение свойств в этом объекте Class1 понадобится INPC (возможно, это объясняет 2 и / или 3)

  6. Не уверен, что это действительно имеет значение.

0 голосов
/ 10 мая 2018

Я думаю, что проблема здесь:

OnAppearing (async):

base.OnAppearing();
lAddress.SetBinding(Label.TextProperty, new Binding("Address");
await vm.LoadDataAsync();

Вы должны установить привязку перед вызовом метода.

...