Показать диалог с MVVM Light toolkit
У меня есть ViewModel, который должен показывать модальное окно (используя ShowDialog()
) при нажатии кнопки. ViewModel ловит команду щелчка, но я не хочу делать window.ShowDialog()
в моей модели ViewModel. Я знаю, что в MVVM Light есть DialogMessage
, но используется для отображения ящиков сообщений, а не модальных окон WPF.
Любые идеи о том, как это сделать?
Ответы
Ответ 1
Вы должны использовать класс 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");
Ответ 2
Это то, что я использую для пользовательских диалогов с 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 ());
Сообщите мне, если мне нужно прояснить любую часть этого для вас.
Ответ 3
Для всех вас, кто хочет действительно простого решения, и все в порядке с не-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 диалогового окна может быть затруднено. Мне не нужна эта функция.
Ответ 4
Вы можете определить интерфейс и его реализацию следующим образом. И, конечно же, с контейнером для инъекций зависимостей, вы должны сделать что-то вроде этого.
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);
}
}