ShowDialog()
)。 ViewModel捕获单击命令,但我不想在ViewModel中执行window.ShowDialog()
。 我知道在MVVM Light中有一个DialogMessage
,但该消息框是用于显示消息框而不是WPF模态窗口。有什么办法可以做到这一点吗?
ShowDialog()
)。 ViewModel捕获单击命令,但我不想在ViewModel中执行window.ShowDialog()
。 我知道在MVVM Light中有一个DialogMessage
,但该消息框是用于显示消息框而不是WPF模态窗口。您应该使用 Messenger
类。在 View
上注册一条消息以显示窗口,然后在需要显示时调用 Messenger
类的 Send
方法。
您可以这样做:
//do this in the 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”);
这是我在使用MVVM-Light Toolkit自定义对话框时所使用的代码。
首先,在应用程序中的某个地方定义这四个类。其中MessageBase类是Toolkit的一部分。
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>
</Window>
接下来,在此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 ());
如果您需要我澄清任何部分,请告诉我。
您可以按照以下方式定义接口及其实现。当然,使用依赖注入容器时,您需要执行类似于此的操作。
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);
}
}
对于所有想要一个非常简单的解决方案并且可以接受不是百分之百纯净 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获取返回值可能会很困难。我不需要那个功能。