MVVM:编辑客户。如何查找具有相同对象的工作空间以及从另一个工作空间创建新工作空间

时间:2009-10-16 19:17:08

标签: wpf vb.net mvvm

就像this question一样,我正在使用the sample created by Josh Smith学习MVVM,我想添加更新功能。

出现两个问题(在提到的问题中没有解决):

  1. 从另一个工作区创建工作区的最佳和最轻松的方法是什么?
  2. 如何查找是否已有工作区编辑同一客户。

2 个答案:

答案 0 :(得分:3)

使用Josh的MvvmFoundation,您可以使用Messenger在ViewModels之间传递消息......

我会这样做:

-1。创建一个Messenger的单例实例,可以在应用程序的任何位置查看。

public class MyMessenger
{
   static Messenger _messenger;
   public static Messenger Messenger
   {
      get
      {
         if (_messenger == null)
            _messenger = new Messenger();
         return _messenger;
      }
   }
}

-2。然后在MainWindowViewModel中注册特定消息的通知 - 您可以轻松定义自己的消息类型,例如

MyMessenger.Messenger.Register<ViewModelBase>("CreateNew", (param) =>
{
  DoWork(param); /* If memory serves, the MainWindowViewModel already has the logic to create a new CustomerViewModel and put it in your Workspaces collection... (which I think answers your second point)  */
});

-3。最后,您需要在原始ViewModel中“通知”此消息,

简单地:

MyMessenger.Messenger.NotifyColleagues("CreateNew", new CustomerViewModel(customerNo));

抱歉 - 我不记得CustomerViewModel的确切结构,但我希望你明白这一点:)

希望这会有所帮助:) 伊恩

答案 1 :(得分:3)

这里有很多事情要发生。你的问题有两个部分(如果我没有遗漏任何东西)。

  1. 如何将双击操作转发到ViewModel中的命令
  2. 如何在此示例中打开“工作区”(在这种情况下,工作区只是一个选项卡)。
  3. 如何对ListViewItem进行DoubleClick,MVVM样式

    有很多方法,但是SO上的这个问题总结得很好: Firing a double click event from a WPF ListView item using MVVM

    我个人使用MarlonGrech的附加行为,所以我会告诉你如何做到这一点:

    <ListView 
          AlternationCount="2" 
          DataContext="{StaticResource CustomerGroups}"
          ...>
          <ListView.ItemContainerStyle>
               <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="acb:CommandBehavior.Event"
                            Value="MouseDoubleClick" />
                    <Setter Property="acb:CommandBehavior.Command"
                            Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}, Path=DataContext.EditCustomerCommand}" />
                    <Setter Property="acb:CommandBehavior.CommandParameter"
                            Value="{Binding}" />
                </Style>
          </ListView.ItemContainerStyle>
    </ListView>
    

    这将绑定到您需要在AllCustomersViewModel中设置的EditCustomerCommand(这将是一个RelayCommand)。

    添加新工作区

    这个更棘手。您会注意到MainWindowViewModel有一个AddWorkspace,但我们实际上没有从AllCustomersViewModel引用该ViewModel。

    我决定(对我而言)最好的方法是创建另一个名为“IWorkspaceCommands”的接口,AllCustomersViewModel将用它来创建新的工作区。这主要是与之前的回答者对Messenger方法的建议形成对比。如果你更喜欢Messenger方法,你可以在这里使用它。

    MainWindowViewModel实际上会实现它,并在创建AllCustomersViewModel时自行传递。

    public interface IWorkspaceCommands
    {
         void AddWorkspace(WorkspaceViewModel view);
    }
    

    这是界面的基本实现。 这包括根据要求检查视图是否已打开(非常简单!):

    #region IWorkspaceCommands Members
    
    public void AddWorkspace(WorkspaceViewModel view)
    {
        if (!Workspaces.Contains(view))
        {
            Workspaces.Add(view);
        }
        SetActiveWorkspace(view);
    }
    
    #endregion
    

    最后,这是我在你的AllCustomersViewModel中告诉你的RelayCommand(以及一些构造函数修改):

    IWorkspaceCommands _wsCommands;
    public AllCustomersViewModel(CustomerRepository customerRepository, IWorkspaceCommands wsCommands)
    {
        _wsCommands = wsCommands;
        EditCustomerCommand = new RelayCommand(EditCustomer);
        ...
    }
    
    public void EditCustomer(object customer)
    {
        CustomerViewModel customerVM = customer as CustomerViewModel;
        _wsCommands.AddWorkspace(customerVM);
    
    }
    

    这就是它。因为您正在处理对用于创建AllCustomersViewModel的相同ViewModel的引用,所以当您在一个屏幕中编辑它时,它会在另一个屏幕中更新,而不会发生事件或消息传递(很好!,但可能不够健壮)。

    ComboBox没有自动选择公司/人的价值,但这仍然存在问题,但这仍然是读者的练习。

    作为今天我的套餐的一部分,我包括一个功能齐全的演示,无需额外费用。 http://dl.getdropbox.com/u/376992/MvvmDemoApp.zip

    希望这有帮助,

    安德森