如何在Xamarin.Forms中实现INotifyPropertyChanged

9 xamarin xamarin.forms

我正在Xamarin.Forms中实现一个购物车.在我的购物车页面中有一个ListView数据.每个单元格都包含一个按钮,用于选择项目数量金额.在购物车视图中,有一个总标签.

我的问题是,当数字选择器改变时,总计不更新.在项目添加视图单元格时调用计算方法.我知道我需要为此实现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));
     }
 }
Run Code Online (Sandbox Code Playgroud)

查看模型

    public BaseViewModel()
    {
        App.Instance.ViewModel = this;
        TempList = TempList ?? new ObservableCollection<cm_items>();
        this.Title = AppResources.AppResource.Cart_menu_title;
        this.Price = CartCell.price;
    }
Run Code Online (Sandbox Code Playgroud)

eak*_*gul 17

作为一种设计方法,最好将MVVM作为子类实现并实现它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));
    }
}
Run Code Online (Sandbox Code Playgroud)

我还强烈建议将ICommand实现为Dictionary结构,如:

public abstract class ViewModelBase : ObservableProperty
{
    public Dictionary<string,ICommand> Commands { get; protected set; }

    public ViewModelBase()
    {
        Commands = new Dictionary<string,ICommand>();
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,ViewModel中的所有待办事项都只是继承ViewModelBase类并使用它

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
}
Run Code Online (Sandbox Code Playgroud)

最后:Xaml用法:

<Entry Placeholder="Username"  Text="{Binding UserName}"/>
<Entry Placeholder="Password" Text="{Binding Password}" IsPassword="True"/>
<Button Text="Login" Command="{Binding Commands[Login]}"/>
Run Code Online (Sandbox Code Playgroud)

  • 我知道这是 5 年前的事了,但对于发现这一点的人来说,我不确定使用字典以这种方式实现 ICommand 是否是一个好习惯,因为它破坏了编译时绑定,在我看来,这是一个有价值的工具。 (4认同)

Jau*_*nka 6

例如尝试这个视图模型:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在继承的类中像这样使用它:

    private int myProperty;
    public int MyProperty
    {
        get { return this.myProperty; }
        set { this.SetPropertyValue(ref this.myProperty, value); }
    }
Run Code Online (Sandbox Code Playgroud)


小智 6

当我开始 Xamarin 编码时,MVVM 有点令人困惑,直到我发现 ViewModel 上的 PropertyChangedEvent 向视图(ContentPage)发出信号,并更新了标签/文本框/等。

对于那些寻找“最新和最好的”的人...以下是一些修改后的代码:

private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    var handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Run Code Online (Sandbox Code Playgroud)

并在您的财产设置器上:

public string SomeProperty
{
    get { return _somProperty; }
    set
    {
       _someProperty= value;
            OnPropertyChanged();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

好的?不?无需每次都传递属性名称!