2012-08-06 76 views
2

我目前使用MVVM(Light)来构建WPF应用程序。但是,在少数情况下,我必须在用户单击按钮时打开一个新对话框(也称为WPF)。但是,这是一场艰苦的战斗。使用MVVM与MVVM打开一个新的对话框

这里是我正在做它:

private void _ShowItemDialog(Item item) 
    { 
     var itemVM = new ItemViewModel(); 
     itemVM.CurrentItem = item ?? new Item(); 
     itemVM.Load(); 

     var itemView = new View.ItemView() { DataContext = itemVM }; 
     if (itemView.ShowDialog() == true) 
     { 
      if (item == null) 
      { 
       itemList.Add(itemVM.CurrentItem); 
      } 
     } 

     itemVM.Cleanup(); 
    } 

而且ItemView控件XAML没有结合到DataContext,否则视图模型的两个不同的实例将被创建。

Window标签内。有在ShowDialog的结果,我用的是DialogCloser代码:

public static class DialogCloser 
    { 
     public static readonly DependencyProperty DialogResultProperty = 
      DependencyProperty.RegisterAttached(
       "DialogResult", 
       typeof(bool?), 
       typeof(DialogCloser), 
       new PropertyMetadata(DialogResultChanged)); 

     private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var window = d as Window; 
      if (window != null) 
       window.DialogResult = e.NewValue as bool?; 
     } 

     public static void SetDialogResult(Window target, bool? value) 
     { 
      target.SetValue(DialogResultProperty, value); 
     } 
    } 

在ItemView控件,这是窗口标签中声明如下:

my:DialogCloser.DialogResult="{Binding DialogResult}" 

当对话框被关闭,而关闭事件将DialogResult设置为true或false。

第一次打开屏幕时可以完美地工作,但是在关闭对话框后无法再次打开对话框。

我想知道你是否有更好的想法来打开对话框,以及为什么这段代码不起作用。

谢谢!

编辑: 我已经修复了代码。我需要做的是创建一个新的ViewModel,并在每次打开对话框时将其附加到DataContext。此外,我不得不从XAML中删除DataContext绑定。请检查上面的代码更改。

通过这些更改,我发现从ViewModelLocator使用ViewModel是不可能的,因为它是一个“单例”,而不是每个新窗口的新实例。因此,DialogResult保存了最后一个值,如果我试图将其值更改回null(因为ViewModel被初始化时)会引发异常。你有任何线索为什么发生这种情况?使用ViewModelLocator的ViewModel对我来说是非常好的,因为它会在整个系统中保持相同的策略。

谢谢!

+0

做我不知道如果我得到你的权利。要为View创建一个新的ViewModel实例,每次生成View时,都可以在后面的Views代码中创建一个ViewModel的实例,并将Views DataContext设置为新生成的ViewModel。 – Andre 2012-08-07 13:03:34

+0

@Andre我不想为每个视图创建一个新的ViewModel。这恰恰相反。我想使用ViewModel单例,但我不明白为什么在打开的新窗口中使用相同的实例不起作用。而且,为什么我不能“擦除”DialogResult? – jpnavarini 2012-08-07 14:03:07

回答

0

我这样做是通过实现静态的XxxxInteraction类来调用的,例如NewUser();该方法打开对话框并做一些工作。在我的ViewModel中,我通过命令调用XxxxInteraction类。

这种实现方式的努力是,您可以轻松地修改静态交互类中使用UnitTests的方法。

public static class UserInteractions 
    { 
     public static User NewUser() 
     { 
      var userDialog = new NewUserDialog(); 
      If(userDialog.ShowDialog() != true) return null; 

      var user = new User(); 
      user.Name = userDialog.Name; 
      user.Age = userDialog.Age; 
      return user; 
     } 
    } 

    public class MyViewModel 
    { 
     ... 

     public void NewUserCommandExecute() 
     { 
      var newUser = UserInteractions.NewUser(); 
      if(newUser == null) return; 

      //Do some with new created user 
     } 
    } 

NewUserDialog是一个普通的Window,它也绑定到ViewModel。

我认为这是实现mvvm模式对话框的好方法。

+0

你是否测试了包含对话框的ViewModels? – Thelonias 2012-08-06 20:14:32

+0

不,我有静态方法的单元测试(实际上我没有在那些方法中创建wpf窗口的实例,我有另一个类为我做了这个 - AskUser.XXX)。 – Andre 2012-08-07 06:38:28

+0

请看看我的文章中添加的编辑部分。谢谢。 – jpnavarini 2012-08-07 12:28:39

0

我前段时间做过这个,我使用对话服务并在我的viewmodel中调用这个服务。 take a look

编辑:顺便说一句,那你必须在你的视图模型

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM); 
+0

请看看我的文章中添加的编辑部分。谢谢。 – jpnavarini 2012-08-07 12:28:00