ボタンのクリック時に(ShowDialog()
を使用して)モーダルウィンドウを表示する必要があるViewModelがあります。 ViewModelはクリックコマンドをキャッチしますが、ViewModel内でwindow.ShowDialog()
を実行したくありません。 MVVMLightにDialogMessage
があることは知っていますが、これはWPFモーダルウィンドウではなくメッセージボックスを表示するために使用されます。
これを行う方法についてのアイデアはありますか?
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”);
これは、MVVM-LightToolkitを使用したカスタムダイアログに使用するものです。
まず、アプリケーションのどこかにこれら4つのクラスを定義します。 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());
};
}
}
3番目に、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());
}
}
第4に、次のビューモデルを定義します。
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);
}
}
5番目に、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 ());
これの一部を明確にする必要がある場合はお知らせください。
本当にシンプルなソリューションが必要で、100%クリーンではない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>
それで全部です。
注意点:ダイアログのビューモデルから戻り値を取得するのは難しい場合があります。その機能は必要ありません。
インターフェイスとその実装は次のように定義できます。そしてもちろん、依存性注入コンテナでは、このような何かをしなければなりません。
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);
}
}