Показать диалог с инструментарием MVVM Light - PullRequest
18 голосов
/ 13 апреля 2011

У меня есть ViewModel, которая должна показывать модальное окно (используя ShowDialog()) при нажатии кнопки.ViewModel ловит команду click, но я не хочу делать window.ShowDialog() в моей ViewModel.Я знаю, что в MVVM Light есть DialogMessage, но он используется для отображения окон сообщений, а не модальных окон WPF.

Есть идеи, как это сделать?

Ответы [ 4 ]

20 голосов
/ 13 апреля 2011

Вы должны использовать 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”);
11 голосов
/ 04 октября 2012

Это то, что я использую для пользовательских диалогов с помощью 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 ());

Дайте мне знать, если мне нужно уточнить какую-либо часть этого для вас.

0 голосов
/ 03 октября 2016

Вы можете определить интерфейс и его реализацию следующим образом. И, конечно же, с контейнером внедрения зависимостей, вы должны сделать что-то вроде этого.

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;

    }

Ваш метод выполнения команды click будет выглядеть следующим образом.

    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);
    }
}
0 голосов
/ 31 октября 2014

Для всех вас, кто хочет действительно простое решение и у которого все в порядке с not-100% -clean-MVVM:
Я хотел открыть диалог подключения из моего главного окна и сделал следующее

Сначала я дал своему MainWindow имя:

<Window x:Name="MainWindow">

Затем я создал команду в моем MainWindowViewModel:

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

Я связал свою кнопку на MainWindow с командой и передал само окно(родительское окно для диалога):

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

Вот и все.

Только предостережение: получение возвращаемых значений из Viewmodel диалогового окна может быть затруднено.Мне не нужна эта функция.

...