web-dev-qa-db-ja.com

MVVMLightツールキットでダイアログを表示する

ボタンのクリック時に(ShowDialog()を使用して)モーダルウィンドウを表示する必要があるViewModelがあります。 ViewModelはクリックコマンドをキャッチしますが、ViewModel内でwindow.ShowDialog()を実行したくありません。 MVVMLightにDialogMessageがあることは知っていますが、これはWPFモーダルウィンドウではなくメッセージボックスを表示するために使用されます。

これを行う方法についてのアイデアはありますか?

20
Tejash

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”);
20
Rafal Spacjer

これは、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 ());

これの一部を明確にする必要がある場合はお知らせください。

11
bugged87

本当にシンプルなソリューションが必要で、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>

それで全部です。

注意点:ダイアログのビューモデルから戻り値を取得するのは難しい場合があります。その機能は必要ありません。

0
JCH2k

インターフェイスとその実装は次のように定義できます。そしてもちろん、依存性注入コンテナでは、このような何かをしなければなりません。

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);
    }
}
0
VivekDev