2014-12-13 4 views
6

Я хотел бы привязать команду к свойству команды моей кнопки. Это казалось довольно простым, поскольку я делал это много раз раньше в WPF, и метод здесь очень похож. Позвольте мне показать некоторые фрагменты кода.Обязательная привязка кнопки не работает в Xamarin.Forms

XAML

<?xml version="1.0" encoding="UTF-8"?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
     x:Class="MyApp.View.CustomPage" 
     Title="Something"> 

<ContentPage.Content> 
    <StackLayout> 
     <Button x:Name="numBtn" Text="Increase number" Command="{Binding IncreaseCommand}" /> 
     <Label x:Name="numLabel" Text="{Binding numberText}" /> 
    </StackLayout> 
</ContentPage.Content> 
</ContentPage> 

Code-за

public partial class CustomPage : ContentPage 
{ 
    public CustomPage() 
    { 
     InitializeComponent(); 
     BindingContext = ViewModelLocator.ViewModel(); //ViewModelLocator is singleton, gives 
                 //you a ViewModel instance 
    } 
} 

ViewModel

public ICommand IncreaseCommand { get; private set; } 
private int number; 
public string numberText { get; private set;} 

конструктор:

public ViewModel() 
{ 
    IncreaseCommand = new Command (() => IncreaseExecuted()); 
    number = 0; 
    numberText = number.ToString(); 
    OnPropertyChanged (numberText); 
} 

, а затем

private void IncreaseExecuted() 
{ 
    number++; 
    numberText = number.ToString(); 
    OnPropertyChanged (numberText); 
} 

Когда я запустить приложение с помощью Xamarin Android Player (KitKat) Я вижу кнопку, и метка чтения 0. Затем я нажимаю кнопку и ничего не происходит. Я попытался проверить, что происходит с точками останова, но приложение не останавливается, даже если они находятся в конструкторе моего ViewModel. Думаю, это как-то связано с эмулятором. Во всяком случае, я думаю, что привязка окончена, так как я вижу «0» на экране. В чем может быть проблема? Позвольте мне показать мой класс ViewModelBase только в случае, если:

ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(String propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Может быть, моя numberText свойство не обновляется, когда я звоню OnPropertyChanged? Но я использовал один и тот же класс ViewModelBase несколько раз раньше, и он всегда работал нормально. Одна последняя вещь, моя страница CustomPage обернута внутри NavigationPage который является дочерним по отношению к TabbedPage:

MainPage.xaml.cs

this.Children.Add (new NavigationPage (new CustomPage()) {Title="Something"}); 

Это не должно ничего повлиять, но там как раз в дело. Так что же случилось с моей привязкой к команде? Заранее спасибо!

ответ

5

Вы почти находитесь. Внимательно посмотрите на ваш вызов метода OnPropertyChanged; вы передаете значение numberText, а не имя. Если вы измените свой код, чтобы передать «numberText», я ожидаю, что он будет работать правильно.

Редактировать: Я должен добавить, что вызов OnPropertyChanged в конструкторе имеет ту же проблему. Причина, по которой вы видите «0» при запуске, заключается в том, что представление просто использует существующую привязку для извлечения значения.

Редактировать 2: Теперь, когда Xamarin поддерживает C# 6.0, вы можете использовать новое выражение «nameof», которое устраняет необходимость в жестко закодированной строке. В качестве альтернативы вы можете использовать классы MVVM MvvmCross, MvvmLight или XLabs.

+0

Вы, кажется, сегодня являетесь моим спасителем! Мой второй вопрос в строке ответил вам. Спасибо огромное! Это была ошибка новобранец, я не знаю, как я мог быть таким глупым. –

+0

Это очень распространенная проблема привязки данных. Поскольку PropertyChangedEventArgs берет строку, ее ОЧЕНЬ легко испортить.Изменения имени из-за рефакторинга - это то место, где я вижу его чаще всего. С этой целью я рекомендую использовать реализацию ViewModelBase, которая принимает выражение как ввод вместо строки, и поэтому вызывает ошибки сборки, если имя свойства изменено без обновления кода активации события. MvvmLight и MvvmCross обе снабжают это. –

+0

Я вижу. Хорошая идея, я собираюсь реализовать это. Спасибо! –

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