Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show dialog with MVVM Light toolkit

Tags:

I have a ViewModel that needs to show a modal window (using ShowDialog()) on a button click. The ViewModel catches the click command, but I don't want to do window.ShowDialog() within my ViewModel. I know there is a DialogMessage in MVVM Light, but that is used to show message boxes, not WPF modal windows.

Any ideas on how to do this?

like image 293
Tejash Avatar asked Apr 13 '11 04:04

Tejash


2 Answers

You should use Messenger class. On the View register a message to show window, and then when you need to show it call Send method of Messenger class.

You can do something like this:

    //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”);
like image 129
Rafal Spacjer Avatar answered Oct 01 '22 21:10

Rafal Spacjer


This is what I use for custom dialogs with the MVVM-Light Toolkit.

First, define these four classes somewhere in your application. The MessageBase class is part of the toolkit.

public class ShowChildWindowMessage : MessageBase { }
public class HideChildWindowMessage : MessageBase { }
public class DisplaySomeContentMessage : MessageBase { }
public class DisplaySomeOtherContentMessage : MessageBase { }

Second, you need a "child" window control. Create a XAML file with the following content:

<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>

Then add the following to the code-behind of this XAML file:

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());
        };
    }

}

Third, add the following to the code-behind of your MainWindow.xaml file:

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());
    }
}

Fourth, define the following view model:

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

Fifth, you create XAML files and view models for the content you want to display in your custom dialog. In this example, my content view models were named SomeContent and SomeOtherContent. You would replace these with what ever you want, of course.

Finally, in order for this to work you must bind your content view models to their respective XAML files by adding the following to your application resources:

<DataTemplate DataType="{x:Type viewmodels:SomeContentVM}">
    <views:SomeContentView/>
</DataTemplate>

<DataTemplate DataType="{x:Type viewmodels:SomeOtherContentVM}">
    <views:SomeOtherContentView/>
</DataTemplate>

Once you get all this set up it is straightforward to add new content (XAML and view models) that can be displayed in your child window. To display the content, simply call the appropriate message using the Messenger class:

Messenger.Default.Send(new DisplaySomeContentMessage ());

Let me know if I need to clarify any part of this for you.

like image 33
bugged87 Avatar answered Oct 01 '22 21:10

bugged87