使用WPF和MVVM打开一个新对话框

时间:2012-08-06 18:32:11

标签: wpf mvvm dialog mvvm-light showdialog

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

以下是我的表现:

    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,否则将创建两个不同的ViewModel实例。

在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中,这在Window标记内声明如下:

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

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

这在第一次打开屏幕时效果很好,但在关闭后无法再次打开对话框。

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

谢谢!

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

通过这些更改,我发现无法使用ViewModelLocator中的ViewModel,因为它是一个“单例”,而不是每个新窗口的新实例。因此,DialogResult保持最后一个值,如果我尝试将其值更改回null(因为它是在初始化ViewModel时),则抛出异常。你有什么线索说明为什么会这样吗?对我来说,使用ViewModelLocator中的ViewModel会非常好,因为它会在整个系统中保持相同的策略。

谢谢!

2 个答案:

答案 0 :(得分:0)

我通过实现具有调用方法的静态XxxxInteraction类来实现,例如NewUser();那些方法打开了Dialogs并做了一些工作。在我的ViewModel中,我通过命令调用XxxxInteraction类。

这种实现方式的努力是,您可以轻松地修改静态Interaction类中的方法以使用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也是一个绑定到ViewModel的普通窗口。

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

答案 1 :(得分:0)

我刚刚做过这个,我使用对话服务并在我的viewmodel中调用此服务。 take a look

编辑:顺便说一句,这就是你在viewmodel中所要做的一切

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