如何从另一个viewmodel调用一个viewmodel的方法

时间:2014-05-26 08:50:21

标签: c# inheritance mvvm windows-runtime win-universal-app

我正在开发Windows Universal app。我有一个GridView,它有一个文本块和一个按钮。 gridview从服务获取未购买对象的数据。该按钮用于购买特定对象。因此,如果用户点击按钮,则购买该对象& gridview会刷新以从中删除购买的商品。

我以简化的方式说明了我的要求。我尝试了两种方法,两种都不起作用。能否请你就此提出解决方案。

我使用的第一种方法是使用Model类继承ViewModel类,以便我可以访问ViewModel类的方法,但它会在StackOverflowException中抛出ViewModelBaseSetProperty<T>方法。

P.S。 - 我不想迁移到MVVMLight等任何框架。

ViewModel.cs

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        DataCollection = new ObservableCollection<Model>();
        for (int i = 1; i < 10; i++)
        {
            DataCollection.Add(new Model { Number = i });
        }
    }

    private ObservableCollection<Model> _DataCollection;
    public ObservableCollection<Model> DataCollection
    {
        get { return _DataCollection; }
        set { this.SetProperty(ref this._DataCollection, value); }
    }
}

Model.cs

public class Model : ViewModel
{
    public RelayCommand<int> DeleteCommand { get; set; }
    public Model()
    {
        DeleteCommand = new RelayCommand<int>((x) => DeleteNumber(x));
    }

    private void DeleteNumber(int x)
    {
        var obj = DataCollection.Where(varNum => varNum.Number == x).FirstOrDefault();
        if (obj != null)
        {
            DataCollection.Remove(obj);
        }
    }

    private int _Number;
    public int Number
    {
        get { return _Number; }
        set { this.SetProperty(ref this._Number, value); }
    }
}

第二种方式我保持隔离,所以我无法访问这些方法。

ViewModel.cs与上面相同

Model.cs

public class Model : ViewModelBase
{
    public RelayCommand<int> DeleteCommand { get; set; }
    public Model()
    {
        DeleteCommand = new RelayCommand<int>((x) => DeleteNumber(x));
    }

    private void DeleteNumber(int x)
    {
        // How to access ViewModel's DataCollection property or 
        // a method which sets un-purchased objects in  DataCollection property
    }

    private int _Number;
    public int Number
    {
        get { return _Number; }
        set { this.SetProperty(ref this._Number, value); }
    }
}

ViewModelBase.cs

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        this.OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好吧,在第一个例子中,你得到了一个StackOverflowException,因为你的ViewModel每次都会实例化9个模型 - 而且由于你的Model是ViewModel的扩展,每个实例都会实例化9个模型并发生无限递归。但是,这并没有回答你的主要问题:)

你的班级名字让我感到困惑,因为在MVVM中有一个&#34;模型&#34;它只是表示操作它的数据和方法,而ViewModel从模型中请求这些数据,并通过可通过绑定从View中检索的公共可访问属性来呈现它。 View了解ViewModel,ViewModel知道Model,而Model只知道数据。在任何情况下,您都不应该直接从视图绑定到模型!

您希望在ViewModel中存放RelayCommand,以便您的View可以绑定到它,并根据您在用户购买项目时要发生的事情(将其存储在数据库中,在另一个变量中跟踪) ,只需从视图中删除而不做任何其他事情,等等。)当发生这种情况时,您可能需要或可能不需要编写额外的逻辑。通常,您希望ViewModel处理用户输入并更新演示文稿对象,并通知模型进行了更改,如果这是您的应用程序所需要的。想想它,因为Model保存实际数据,而ViewModel只保存用户看到的内容。

不幸的是,如果不知道自己要做的更多细节,那么很难给出比这更具体的建议!