我的绑定标签未更改[INotifyPropertyChanged]

时间:2017-09-02 13:22:36

标签: c# xamarin xamarin.forms

我最近开始学习Xamarin,我偶然发现了以下问题。我的XAML文件中有一个绑定到ViewModel属性的标签。我正在使用ICommand接口将轻击手势绑定到我的ViewModel中的方法,该方法应该更新标签的文本。但是,它没有更新“请一次触摸我!”。我只是想知道我在这里做错了什么?

MainPage xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:App1"
         x:Class="App1.MainPage">

<Label Text="{Binding MessageContent, Mode=TwoWay}"
       VerticalOptions="Center"
       HorizontalOptions="Center">
    <Label.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding OnLabelTouchedCmd}" />
    </Label.GestureRecognizers>

</Label>

</ContentPage>

代码隐藏:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        BindingContext = new MainPageViewModel();
    }
}

视图模型:

class MainPageViewModel : INotifyPropertyChanged
{
    private string _messageContent;

    public MainPageViewModel()
    {
        MessageContent = "Please touch me once!";

        OnLabelTouchedCmd = new Command(() => { MessageContent = "Hey, stop toutching me!"; });
    }

    public ICommand OnLabelTouchedCmd { get; private set; }

    public string MessageContent
    {
        get => _messageContent;
        set
        {
            _messageContent = value;
            OnPropertyChanged(value);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;


    protected virtual void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3 个答案:

答案 0 :(得分:3)

您正在使用错误的参数调用OnPropertyChanged,如下所示:

protected virtual Void OnPropertyChanged ([System.Runtime.CompilerServices.CallerMemberName] String propertyName)

它期望属性的名称而不是您现在传递的值。试试这个:

public string MessageContent
{
    get => _messageContent;
    set
    {
        _messageContent = value;
         OnPropertyChanged("MessageContent");
    }
}

答案 1 :(得分:1)

当前代码无效,因为它正在将value属性传递给OnPropertyChanged

相反,我们需要将属性的名称作为string传递给OnPropertyChanged

答案

我们可以利用CallerMemberName属性使代码更简洁,并在调用OnPropertyChanged时避免硬编码字符串。

[CallerMemberName]添加到OnPropertyChanged的参数允许您从属性的setter中调用OnPropertyChanged(),并且属性名称会自动传递给参数。

更新方法

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

更新了ViewModel

class MainPageViewModel : INotifyPropertyChanged
{
    private string _messageContent;

    ...

    public string MessageContent
    {
        get => _messageContent;
        set
        {
            _messageContent = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

答案 2 :(得分:0)

另请查看位于here的ViewModelBase,让所有ViewModel都从中继承。您可以通过以下两种方式之一调用OnPropertyChanged。第一个只是取名为调用成员,在这种情况下是你的公共财产。

OnPropertyChanged();

OnPropertyChanged("MyProperty");

编辑 - 这是Brandon正确答案的延伸