使用MVVM Light工具包显示对话框

时间:2011-04-13 04:37:50

标签: mvvm dialog mvvm-light

我有一个ViewModel需要在按钮点击时显示一个模态窗口(使用ShowDialog())。 ViewModel捕获click命令,但我不想在ViewModel中执行window.ShowDialog()。我知道MVVM Light中有一个DialogMessage,但它用于显示消息框,而不是WPF模式窗口。

关于如何做到这一点的任何想法?

4 个答案:

答案 0 :(得分:20)

您应该使用Messenger课程。在View上注册要显示的消息窗口,然后在需要显示它时调用Send类的Messenger方法。

您可以这样做:

//do this in code behind file of your View
Messenger.Default.Register<string>(this, ShowWindow);

private void ShowWindow(string message)
{
    // your logic here
}

// In the ViewModel
Messenger.Default.Send(“Some text”);

答案 1 :(得分:11)

这是我用于MVVM-Light Toolkit的自定义对话框。

首先,在应用程序的某处定义这四个类。 MessageBase类是工具包的一部分。

public class ShowChildWindowMessage : MessageBase { }
public class HideChildWindowMessage : MessageBase { }
public class DisplaySomeContentMessage : MessageBase { }
public class DisplaySomeOtherContentMessage : MessageBase { }

其次,你需要一个“子”窗口控件。使用以下内容创建XAML文件:

<Window x:Class="ChildWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding Path=ChildWindowBinding, Source={StaticResource Locator}}"
    Title="{Binding Path=CurrentContent.DisplayName}"
    MinWidth="300" MinHeight="125" SizeToContent="WidthAndHeight"
    ShowInTaskbar="False" WindowState="Normal" ResizeMode="NoResize"
    WindowStartupLocation="CenterOwner" SnapsToDevicePixels="True">

<Grid>
    <ContentPresenter Content="{Binding Path=CurrentContent}" />
</Grid>

然后将以下内容添加到此XAML文件的代码隐藏中:

public partial class ChildWindowView : Window
{
    public ChildWindowView(Window owner)
    {
        InitializeComponent();
        Owner = owner;

        Closing += (s, e) => 
        {
            // window reused so just hide
            e.Cancel = true;
            Messenger.Default.Send(new HideChildWindowMessage());
        };
    }

}

第三,将以下内容添加到MainWindow.xaml文件的代码隐藏中:

public partial class MainWindowView : Window
{
    private ChildWindowView m_childWindowView;

    public MainWindowView()
    {
        InitializeComponent();
        Closing += (s, e) => ViewModelLocator.CleanUp();
        Loaded += (s, e) =>
        {
            m_childWindowView = new ChildWindowView(this);
        };

        Messenger.Default.Register<ShowChildWindowMessage>(this, (msg) => m_childWindowView.ShowDialog());
        Messenger.Default.Register<HideChildWindowMessage>(this, (msg) => m_childWindowView.Hide());
    }
}

第四,定义以下视图模型:

public class ChildWindowVM : ViewModelBase
{
    private ViewModelBase m_currentContent;
    public ViewModelBase CurrentContent
    {
        get { return m_currentContent; }
        set
        {
            m_currentContent = value;
            RaisePropertyChanged("CurrentContent");

            if (m_currentContent != null)
            {
                Messenger.Default.Send(new ShowChildWindowMessage());
            }
        }
    }

    public ChildWindowVM()
    {
        Messenger.Default.Register<DisplaySomeContentMessage>(this, (msg) => CurrentContent = ViewModelLocator.SomeContentVm);
        Messenger.Default.Register<DisplaySomeOtherContentMessage>(this, (msg) => CurrentContent = ViewModelLocator.SomeOtherContentVm);
    }
}

第五,您创建XAML文件并查看要在自定义对话框中显示的内容的模型。在此示例中,我的内容视图模型名为SomeContent和SomeOtherContent。当然,你可以用你想要的东西替换它们。

最后,为了实现这一点,您必须将以下内容添加到应用程序资源中,将内容视图模型绑定到各自的XAML文件:

<DataTemplate DataType="{x:Type viewmodels:SomeContentVM}">
    <views:SomeContentView/>
</DataTemplate>

<DataTemplate DataType="{x:Type viewmodels:SomeOtherContentVM}">
    <views:SomeOtherContentView/>
</DataTemplate>

现在,一旦完成所有这些设置,就可以很容易地添加可以在子窗口中显示的新内容(XAML和视图模型)。要显示内容,只需使用Messenger类调用相应的消息:

Messenger.Default.Send(new DisplaySomeContentMessage ());

如果我需要为您澄清这方面的任何部分,请告诉我。

答案 2 :(得分:0)

对于那些想要一个非常简单的解决方案并且没有-100%-clean-MVVM的人来说: 我想从主窗口打开一个连接对话框并执行以下操作

首先,我给了我的MainWindow一个名字:

<Window x:Name="MainWindow">

然后我在MainWindowViewModel中创建了一个Command:

public ICommand AddInterfaceCommand
{
    get
    {
        return new RelayCommand<Window>((parentWindow) =>
        {
            var wizard = new ConnectionWizard();
            wizard.Owner = parentWindow;
            wizard.ShowDialog();
        }
    }
}

我将MainWindow上的Button绑定到Command并传递了窗口本身(对话框的父窗口):

<Button Command="{Binding AddInterfaceCommand}" CommandParameter="{Binding ElementName=MainWindow}">Add interface</Button>

就是这样。

唯一警告:从Dialog的Viewmodel获取返回值可能很困难。我不需要这个功能。

答案 3 :(得分:0)

您可以按如下方式定义接口及其实现。而且依赖于依赖注入容器,你必须做这样的事情。

NInjectKernel.Bind<IMessageBoxService>().To<MessageBoxService>();

您的ViewModel看起来像这样。

    private IMessageBoxService _MBService;
    public DropboxSettingsViewModel(IDropboxService dbService, IMessageBoxService mbService)
    {
        if (dbService == null)
            throw new ArgumentNullException("IDropboxService is null");

        _DropboxService = dbService;

        if (mbService == null)
            throw new ArgumentNullException("MessageBoxService is null");

        _MBService = mbService;

    }

您的点击命令执行方法如下。

    private void ConfigureDropboxExecute(object obj)
    {

        _MBService.Show("Error Occured Authenticating dropbox", "Dropbox Authentication", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);

    }


public interface  IMessageBoxService
{
    MessageBoxResult Show(string messageBoxText);
    MessageBoxResult Show(string messageBoxText, string caption);
    MessageBoxResult Show(Window owner, string messageBoxText);
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);
    MessageBoxResult Show(Window owner, string messageBoxText, string caption);
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button);
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult);
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options);
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult);
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options);
}

使用System.Windows;

public class MessageBoxService : IMessageBoxService
{
    public MessageBoxResult Show(string messageBoxText)
    {
        return MessageBox.Show(messageBoxText);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText)
    {
        return MessageBox.Show(owner, messageBoxText);
    }

    public MessageBoxResult Show(string messageBoxText, string caption)
    {
        return MessageBox.Show(messageBoxText, caption);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption)
    {
        return MessageBox.Show(owner, messageBoxText, caption);
    }

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
    {
        return MessageBox.Show(messageBoxText, caption, button);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button)
    {
        return MessageBox.Show(owner, messageBoxText, caption, button);
    }

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
    {
        return MessageBox.Show(messageBoxText, caption, button, icon);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
    {
        return MessageBox.Show(owner, messageBoxText, caption, button, icon);
    }

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
    {
        return MessageBox.Show(messageBoxText, caption, button, icon, defaultResult);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
    {
        return MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult);
    }

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
    {
        return MessageBox.Show(messageBoxText, caption, button, icon, defaultResult, options);
    }

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
    {
        return MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult, options);
    }
}