【问题标题】:How to call one viewmodel's method from another viewmodel如何从另一个视图模型调用一个视图模型的方法
【发布时间】:2014-05-26 08:50:21
【问题描述】:

我正在开发 Windows 通用应用程序。我有一个 GridView,它有一个文本块和一个按钮。网格视图从服务中获取未购买对象的数据。该按钮用于购买特定对象。因此,如果用户单击购买了该对象的按钮,并且 gridview 会刷新以从中删除购买的项目。

我正在以简化的方式说明我的要求。我尝试了两种方法,都不起作用。你能建议我解决这个问题吗?

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

附: - 我不想迁移到任何框架,如 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); }
    }
}

模型.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 同上

模型.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));
        }
    }
}

【问题讨论】:

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


    【解决方案1】:

    好吧,在第一个示例中,您会收到 StackOverflowException 异常,因为您的 ViewModel 每次都会实例化 9 个模型 - 并且由于您的模型是 ViewModel 的扩展,因此每个模型都会再实例化 9 个模型,并且会发生无限递归。不过,这并不能回答您的主要问题:)

    您的类名让我感到困惑,因为在 MVVM 中,“模型”只是数据和操作它的方法的表示,而 ViewModel 从模型请求此数据并通过检索到的可公开访问的属性呈现它从视图通过绑定。 View 知道 ViewModel,ViewModel 知道 Model,而 Model 只知道数据。在任何情况下,您都不应该直接从视图绑定到模型!

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

    不幸的是,如果不知道你想做什么更详细一点,很难给出比这更具体的建议!

    【讨论】:

    • 请不要找名字。如果您有我的要求,请告诉我如何刷新DataCollection?刷新意味着,通过按钮命令购买的物品将从DataCollection中删除。
    • 好吧,您必须从收藏中删除购买的商品,这与第一个示例中的 DeleteNumber 方法类似。然后,您需要在视图绑定的对象或对象集合上引发 PropertyChanged,以便视图知道集合已更改。
    • 我认为第一个例子没有用,因为它抛出了StackOverflowExecption。如何从Model 中删除ViewModel 类的属性对象?两者之间没有关系(参考)。如何调用该方法?我敦促您以代码的形式给我解决方案,因为我的时间不多了:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 2021-05-14
    相关资源
    最近更新 更多