0

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

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

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

PS - 我不想迁移到任何框架,如 MVVMLight 等。

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

1 回答 1

0

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

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

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

不幸的是,如果不知道您要更详细地做什么,很难给出比这更具体的建议!

于 2014-05-27T03:24:55.610 回答