【问题标题】:Passing parameters between viewmodels在视图模型之间传递参数
【发布时间】:2013-10-22 09:08:47
【问题描述】:

在我的应用中,我有 2 个视图。列表(GridView)和表单。我正在更改此线程中提出的观点: WPF MVVM switch usercontrols

现在我有一个问题,如何在单击编辑后传递所选项目的 id 以使用编辑表单显示新视图。

列出所有项目、添加新项目、删除和编辑的简单应用程序。我怎样才能在 MVVWM 中做到这一点?


更新

我只想创建一个简单的应用程序,左侧有菜单:

  1. 列表
  2. 添加新的。

当单击列表时,它会显示带有列表和 3 个按钮的 UC:添加、编辑、删除。单击添加后,编辑它会显示带有特定值的 UC(在编辑时)。我怎样才能做到这一点??

【问题讨论】:

  • 您的视图模型之间是否有共同的父级?
  • 我有 MainWindow 和其他 ViewModel 的 ObservableCollection 并且在窗口的右侧我有:

标签: wpf mvvm


【解决方案1】:

据我了解,您想要这样的东西:

这样当您单击Add 时,它会显示:

对吗?

所以你需要以下行为:

  • 添加不需要任何 ID。
  • 添加完成后必须重新加载列表。
  • Edit 接收列表的选定项 ID。
  • 添加完成后必须重新加载列表。

我假设您正在使用某个存储库。

我提出以下 MVVM 结构:

  • MainViewModel:主屏幕的 DataContext。
    • BaseViewModel RightViewModel:视图模型的容器显示在屏幕右侧。
    • ICommand ViewListCommand:通过创建ListViewModel 的新实例并将其分配给BaseViewModel 属性来显示列表。
    • ICommand AddNewCommand:通过创建 AddViewModel 的新实例并将其分配给 BaseViewModel 属性来显示 addnew 屏幕。

然后:

  • ListViewModel:单击 List 时屏幕右侧的 DataContext。
    • List<Items> Items:提供要显示的项目。
    • Item SelectedItem:将绑定到 UI 上的 SelectedItem 的属性。
    • ICommand EditCommand:该命令将获取所选项目并通知必须编辑的 MainViewModel。

所以在某些时候,视图模型会收到来自子视图模型的通知(即列表会告诉主视图进行编辑)。我建议通过使用事件来做到这一点:

public class Item
{
    public string Name { get; set; }
}

public class ItemEventArgs : EventArgs
{
    public Item Item { get; set; }

    public ItemEventArgs(Item selectedItem)
    {
        this.Item = selectedItem;
    }
}

public class BaseViewModel
{

}

public class ListViewModel : BaseViewModel
{
    public event EventHandler<ItemEventArgs> EditItem;

    public Item SelectedItem { get; set; }

    public ICommand EditItemCommand { get; private set; }

    public ListViewModel()
    {
        this.EditItemCommand = new DelegateCommand(() => this.EditItem(this, new ItemEventArgs(this.SelectedItem)));
    }
}

public class EditViewModel : BaseViewModel
{

}

public class MainViewModel
{
    public BaseViewModel RightViewModel { get; private set; }

    public ICommand ViewListCommand { get; private set; }

    public MainViewModel()
    {
        this.ViewListCommand = new DelegateCommand(() =>
        {
            // unhook possible previous events
            var listViewModel = new ListViewModel();
            listViewModel.EditItem += listViewModel_EditItem;
            this.RightViewModel = listViewModel;
        });
    }

    void listViewModel_EditItem(object sender, ItemEventArgs e)
    {
        // unhook possible previous events
        var editViewModel = new EditViewModel();
        this.RightViewModel = editViewModel;
    }

}

xaml 绑定不是必需的,因为它会非常向前。

这是一个非常基本的例子,说明我认为如何处理这类事情。这里重要的是正确解开事件,否则会遇到问题。

这类东西你也可以看看Reactive UI

【讨论】:

  • 优雅的解决方案,这也是我会做的。
【解决方案2】:

如果您有一个共同的视图模型父级,那么您可以使用该父级为您传递参数值。只需在相关视图模型中设置一个或多个delegates:

在带有相关参数的视图模型中更新...我们称之为ParameterViewModel

public delegate void ParameterChange(string parameter);

public ParameterChange OnParameterChange { get; set; }

在父级中:

ParameterViewModel viewModel = new ParameterViewModel();
viewModel.OnParameterChange += ParameterViewModel_OnParameterChange;
ListMenu.Add(viewModel);
// Add other view models

参数变化时返回ParameterViewModel

public string Parameter
{
    get { return parameter; }
    set
    {
        parameter = value;
        NotifyPropertyChanged("Parameter");
        // Always check for null
        if (OnParameterChange != null) OnParameterChange(parameter);
    }
}

现在在父视图模型中:

public void ParameterViewModel_OnParameterChange(string parameter)
{
    // Do something with the new parameter data here
    AnotherViewModel anotherViewModel = (AnotherViewModel)ListMenu[someIndex];
    anotherViewModel.Parameter = parameter;
}

您可以从 MSDN 上的 Delegates (C# Programming Guide) 页面了解有关使用 delegate 对象的更多信息。

【讨论】:

  • 我只想创建一个简单的应用程序,左侧有菜单: 1. 列表 2. 添加新的。单击列表时,它会显示带有列表和 3 个按钮的 UC:添加、编辑、删除。单击添加后,编辑它会显示带有特定值的 UC(在编辑时)。我怎样才能做到这一点??
  • 这就是为什么您应该将所有这些(新)信息放入您的问题中,而不是在用户花时间回答您的原始问题之后的评论中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 2017-09-02
相关资源
最近更新 更多