我最近开始学习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));
}
}
答案 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));
}
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正确答案的延伸