【问题标题】:My binded Label is not changed [INotifyPropertyChanged]我的绑定标签未更改 [INotifyPropertyChanged]
【发布时间】:2017-09-02 13:22:35
【问题描述】:

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

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

【问题讨论】:

    标签: c# xamarin xamarin.forms


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 这就是问题所在。谢谢!我认为我应该提供已更改属性的新值,但它应该是正在更改的属性本身。
    【解决方案2】:

    说明

    当前代码不起作用,因为它将属性的value 传递给OnPropertyChanged

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

    回答

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

    OnPropertyChanged的参数中添加[CallerMemberName]可以让你从属性的setter中调用OnPropertyChanged(),属性名会自动传入参数中。

    更新方法

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

    更新的视图模型

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

    【讨论】:

      【解决方案3】:

      同时查看位于here 的 ViewModelBase,让您的所有 ViewModel 都继承自它。您可以通过以下两种方式之一仅调用 OnPropertyChanged。其中第一个将只取调用成员的名称,在这种情况下是您的公共财产。

      OnPropertyChanged();
      
      OnPropertyChanged("MyProperty");
      

      编辑-这是对布兰登正确答案的扩展

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-08
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 2011-02-18
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多