如何在 Xamarin.Forms 中实现 INotifyPropertyChanged
How to implement INotifyPropertyChanged in Xamarin.Forms
我正在 Xamarin.Forms 中实现购物车。在我的购物车页面中有一个包含数据的 ListView
。每个单元格都包含一个按钮,用于 select item 和 amount 的计数。在购物车视图中有一个总计标签。
我的问题是总计没有在数字选择器更改时更新。计算方法在项目添加视图单元格时调用。我知道我需要为此实施 INotifyProperty
,但我不确定该怎么做。
我有一个继承 INotifyProperty
的基础视图模型,其中包含一个事件。
public class BaseViewModel : INotifyPropertyChanged
{
private double _price;
public double Price
{
get
{
return _price;
}
set
{
_price = value;
OnPropertyChanged("Price");}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
查看模型
public BaseViewModel()
{
App.Instance.ViewModel = this;
TempList = TempList ?? new ObservableCollection<cm_items>();
this.Title = AppResources.AppResource.Cart_menu_title;
this.Price = CartCell.price;
}
例如试试这个视图模型:
public abstract class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetPropertyValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (value == null ? field != null : !value.Equals(field))
{
field = value;
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
return true;
}
return false;
}
}
并在继承 类 中像这样使用它:
private int myProperty;
public int MyProperty
{
get { return this.myProperty; }
set { this.SetPropertyValue(ref this.myProperty, value); }
}
作为一种设计方法,最好将 MVVM 实现为子class 并将其实现到您的 ViewModel
。
示例实现:
public class ObservableProperty : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
我还强烈建议将 ICommand 实现为字典结构,例如:
public abstract class ViewModelBase : ObservableProperty
{
public Dictionary<string,ICommand> Commands { get; protected set; }
public ViewModelBase()
{
Commands = new Dictionary<string,ICommand>();
}
}
所以您的 ViewModel 中所有待办事项只是继承 ViewModelBase class 并使用它
class LoginViewModel : ViewModelBase
{
#region fields
string userName;
string password;
#endregion
#region properties
public string UserName
{
get {return userName;}
set
{
userName = value;
OnPropertyChanged("UserName");
}
}
public string Password
{
get{return password;}
set
{
password = value;
OnPropertyChanged("Password");
}
}
#endregion
#region ctor
public LoginViewModel()
{
//Add Commands
Commands.Add("Login", new Command(CmdLogin));
}
#endregion
#region UI methods
private void CmdLogin()
{
// do your login jobs here
}
#endregion
}
最后:Xaml 用法:
<Entry Placeholder="Username" Text="{Binding UserName}"/>
<Entry Placeholder="Password" Text="{Binding Password}" IsPassword="True"/>
<Button Text="Login" Command="{Binding Commands[Login]}"/>
当我开始 Xamarin 编码时,MVVM 有点混乱,直到我发现 ViewModel 上的 PropertyChangedEvent 向 View (ContentPage) 发出信号,并更新了 Label/textbox/etc.
对于那些寻找 'latest and greatest'...的人来说,这是一些修改后的代码:
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
和你的 属性 Setter:
public string SomeProperty
{
get { return _somProperty; }
set
{
_someProperty= value;
OnPropertyChanged();
}
}
}
好看吗?不?省去了每次都必须传递 属性 名称!
我正在 Xamarin.Forms 中实现购物车。在我的购物车页面中有一个包含数据的 ListView
。每个单元格都包含一个按钮,用于 select item 和 amount 的计数。在购物车视图中有一个总计标签。
我的问题是总计没有在数字选择器更改时更新。计算方法在项目添加视图单元格时调用。我知道我需要为此实施 INotifyProperty
,但我不确定该怎么做。
我有一个继承 INotifyProperty
的基础视图模型,其中包含一个事件。
public class BaseViewModel : INotifyPropertyChanged
{
private double _price;
public double Price
{
get
{
return _price;
}
set
{
_price = value;
OnPropertyChanged("Price");}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
查看模型
public BaseViewModel()
{
App.Instance.ViewModel = this;
TempList = TempList ?? new ObservableCollection<cm_items>();
this.Title = AppResources.AppResource.Cart_menu_title;
this.Price = CartCell.price;
}
例如试试这个视图模型:
public abstract class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetPropertyValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (value == null ? field != null : !value.Equals(field))
{
field = value;
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
return true;
}
return false;
}
}
并在继承 类 中像这样使用它:
private int myProperty;
public int MyProperty
{
get { return this.myProperty; }
set { this.SetPropertyValue(ref this.myProperty, value); }
}
作为一种设计方法,最好将 MVVM 实现为子class 并将其实现到您的 ViewModel
。
示例实现:
public class ObservableProperty : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
我还强烈建议将 ICommand 实现为字典结构,例如:
public abstract class ViewModelBase : ObservableProperty
{
public Dictionary<string,ICommand> Commands { get; protected set; }
public ViewModelBase()
{
Commands = new Dictionary<string,ICommand>();
}
}
所以您的 ViewModel 中所有待办事项只是继承 ViewModelBase class 并使用它
class LoginViewModel : ViewModelBase
{
#region fields
string userName;
string password;
#endregion
#region properties
public string UserName
{
get {return userName;}
set
{
userName = value;
OnPropertyChanged("UserName");
}
}
public string Password
{
get{return password;}
set
{
password = value;
OnPropertyChanged("Password");
}
}
#endregion
#region ctor
public LoginViewModel()
{
//Add Commands
Commands.Add("Login", new Command(CmdLogin));
}
#endregion
#region UI methods
private void CmdLogin()
{
// do your login jobs here
}
#endregion
}
最后:Xaml 用法:
<Entry Placeholder="Username" Text="{Binding UserName}"/>
<Entry Placeholder="Password" Text="{Binding Password}" IsPassword="True"/>
<Button Text="Login" Command="{Binding Commands[Login]}"/>
当我开始 Xamarin 编码时,MVVM 有点混乱,直到我发现 ViewModel 上的 PropertyChangedEvent 向 View (ContentPage) 发出信号,并更新了 Label/textbox/etc.
对于那些寻找 'latest and greatest'...的人来说,这是一些修改后的代码:
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
和你的 属性 Setter:
public string SomeProperty
{
get { return _somProperty; }
set
{
_someProperty= value;
OnPropertyChanged();
}
}
}
好看吗?不?省去了每次都必须传递 属性 名称!