I want to ask which is the best way to show child windows using the MVVM pattern and the MVVMLight framework. I have read a couple of threads here in this site but I don't seem to comprehence what exactly the code written is doing, so please provide a detailed explanation with your ideas.
-
Do you have anything to show so far? There are some good examples available: [Link 1](http://thesoftwarechef.blogspot.co.uk/2013/09/mvvm-light-wpf-and-opening-new-windows_5.html) | [Link 2](http://stackoverflow.com/questions/14198443/best-pratice-to-open-a-new-window-in-mvvm-light-with-parameters) – Nov 27 '13 at 08:53
2 Answers
i use a service to show new windows or new dialogs.
you can check my first version for dialogs here
i added some more overloads to my interface the last days
public interface IUIDialogWindowService
{
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext);
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<param name="minHeigth">Minimum Height</param>
///<param name="minWidth">Minimum Width</param>
///<param name="maxHeigth">Maximum Height</param>
///<param name="maxWidth">Maximum Width</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext, double minHeigth = 0, double minWidth=0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity);
/// <summary>
/// Zeigt ein Dialog an
/// </summary>
/// <param name="titel">Titel für den Dialog<</param>
/// <param name="datacontext">DataContext für den Dialog</param>
/// <param name="settings">ApplicationsSetting für Height and Width</param>
/// <param name="pathHeigthSetting">Name für Height Setting</param>
/// <param name="pathWidthSetting">Name für Width Setting</param>
/// <param name="minHeigth">Minimum Height</param>
/// <param name="minWidth">Minimum Width</param>
/// <param name="maxHeigth">Maximum Height</param>
/// <param name="maxWidth">Maximum Width</param>
/// <returns>true wenn DialogResult=true, ansonsten false</returns>
bool? ShowDialog(string titel, object datacontext, ApplicationSettingsBase settings, string pathHeigthSetting, string pathWidthSetting, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity);
}
///<summary>
/// Implementierung von <see cref="IUIDialogWindowService"/>
///</summary>
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IUIDialogWindowService))]
public class WpfUIDialogWindowService : IUIDialogWindowService
{
#region Implementation of IUIDialogWindowService
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext)
{
var win = new DialogWindow {Title = titel, DataContext = datacontext};
return win.ShowDialog();
}
///<summary>
/// Zeigt ein Dialog an.
///</summary>
///<param name="titel">Titel für den Dialog</param>
///<param name="datacontext">DataContext für den Dialog</param>
///<param name="minHeigth">Minimum Height</param>
///<param name="minWidth">Minimum Width</param>
///<param name="maxHeigth">Maximum Height</param>
///<param name="maxWidth">Maximum Width</param>
///<returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity)
{
var win = new DialogWindow { Title = titel, DataContext = datacontext };
win.MinHeight = minHeigth;
win.MinWidth = minWidth;
win.MaxHeight = maxHeigth;
win.MaxWidth = maxWidth;
return win.ShowDialog();
}
/// <summary>
/// Zeigt ein Dialog an
/// </summary>
/// <param name="titel">Titel für den Dialog<</param>
/// <param name="datacontext">DataContext für den Dialog</param>
/// <param name="settings">ApplicationsSetting für Height and Width</param>
/// <param name="pathHeigthSetting">Name für Height Setting</param>
/// <param name="pathWidthSetting">Name für Width Setting</param>
/// <param name="minHeigth">Minimum Height</param>
/// <param name="minWidth">Minimum Width</param>
/// <param name="maxHeigth">Maximum Height</param>
/// <param name="maxWidth">Maximum Width</param>
/// <returns>true wenn DialogResult=true, ansonsten false</returns>
public bool? ShowDialog(string titel, object datacontext, ApplicationSettingsBase settings, string pathHeigthSetting, string pathWidthSetting, double minHeigth = 0, double minWidth = 0, double maxHeigth = double.PositiveInfinity, double maxWidth = double.PositiveInfinity)
{
var win = new DialogWindow { Title = titel, DataContext = datacontext };
win.MinHeight = minHeigth;
win.MinWidth = minWidth;
win.MaxHeight = maxHeigth;
win.MaxWidth = maxWidth;
try
{
if(settings != null)
{
win.SizeToContent = SizeToContent.Manual;
var height = settings[pathHeigthSetting];
var width = settings[pathWidthSetting];
BindingOperations.SetBinding(win, FrameworkElement.HeightProperty, new Binding(pathHeigthSetting) { Source = settings, Mode = BindingMode.TwoWay });
BindingOperations.SetBinding(win, FrameworkElement.WidthProperty, new Binding(pathWidthSetting) { Source = settings, Mode = BindingMode.TwoWay });
win.Height = (double)height;
win.Width = (double)width;
}
}
catch
{
win.SizeToContent = SizeToContent.WidthAndHeight;
}
return win.ShowDialog();
}
#endregion
}
For the sake of completeness:
<Window x:Class="DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
WindowStyle="SingleBorderWindow"
WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight"
Style="{DynamicResource {x:Type Window}}">
<ContentPresenter x:Name="DialogPresenter" Content="{Binding .}">
</ContentPresenter>
</Window>
public partial class DialogWindow : Window
{
public DialogWindow()
{
InitializeComponent();
this.DialogPresenter.DataContextChanged += DialogPresenterDataContextChanged;
}
private void DialogPresenterDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var d = e.NewValue as IDialogResultVMHelper;
if (d == null)
return;
d.RequestCloseDialog += new EventHandler<RequestCloseDialogEventArgs>(DialogResultTrueEvent).MakeWeak(eh => d.RequestCloseDialog -= eh);
}
private void DialogResultTrueEvent(object sender, RequestCloseDialogEventArgs eventargs)
{
this.DialogResult = eventargs.DialogResult;
}
}
public class RequestCloseDialogEventArgs : EventArgs
{
public RequestCloseDialogEventArgs(bool dialogresult)
{
this.DialogResult = dialogresult;
}
public bool DialogResult
{
get; set;
}
}
public interface IDialogResultVMHelper
{
event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog;
}
-
-
-
well I did say I am a newbie so most of it is not understandable to me – EnvelopedDevil Nov 27 '13 at 15:59
First a question, and a counter-intuitive one. What does the opening a new window action have to do with MVVM?
I personally don't think there is any connection at all. In fact like several other UI constructs, it's something that happens totally in the View layer. There are several other concepts like this,
- A navigation based interface (using NavigationWindow) where data is filled into a form and
Next
is pressed in order to change to the next page - A context menu that opens with a variable set of operations
- A tabbed control that dynamically loads the active page
All of these things are different ways of displaying new views to the user. All of them exist in the View tier only by presenting new UI elements that are bound to ViewModels.
However... there are lots of patterns that have evolved around MVVM to support this. Commonly this is the use of a service or a controller to handle the view operations, check to see if the MVVM library of your choice supports means of showing a new view.
Finally one thing that caught me out for a while, is what happens when you need to both perform an operation and change the view. Normally you would bind the UI object (e.g. a button) to a ViewModel level command to perform the action, and rely on binding to update the UI controls showing the new values. Since the ViewModel shouldn't know about the View then any operations that change the UI have to occur solely in the View. This means that you can't bind to a ViewModel command. Fortunately you can create a command at the view level that delegates to the view model level operation and changes the UI.
(Hmm... Reading back, not sure this answers the question, but it might help clarify your thinking)

- 6,868
- 1
- 26
- 39
-
well as much as I understood some things are ok to be written in the codebehind just like the opening and closing of another view because there is no connection to any view model in this case, am I right – EnvelopedDevil Nov 27 '13 at 15:44
-
Yes, although I'm not suggesting code-behind is the right way to write UIs, but that does work. Consider what it should mean (to your VM & M) if you decided to take your application and replace the entire View with a different one. e.g. you want a wizard to walk a new user through the steps, but a single dialog for the Power Users. They should do the same thing and be bound to the same ViewModel data, but just look different. – AlSki Nov 27 '13 at 16:11