I'm pretty much new to the MVVM architecture design...
I was struggling lately to find a suitable control already written for such a purpose but had no luck, so I reused parts of XAML from another similar control and got make my own.
What I want to achieve is:
Have a reusable View (usercontrol) + viewmodel (to bind to) to be able to use inside other views as a modal overlay showing a dialog that disables the rest of the view, and shows a dialog over the it.
How I wanted to implement it:
- create a viewmodel that takes string(message) and action+string collection(buttons)
- viewmodel creates a collection of ICommands that call those actions
- dialog view binds to the its viewmodel that will be exposed as property of another viewmodel (parent)
- dialog view is put into the xaml of the parent like this:
pseudoXAML:
<usercontrol /customerview/ ...>
<grid>
<grid x:Name="content">
<various form content />
</grid>
<ctrl:Dialog DataContext="{Binding DialogModel}" Message="{Binding Message}" Commands="{Binding Commands}" IsShown="{Binding IsShown}" BlockedUI="{Binding ElementName=content}" />
</grid>
</usercontrol>
So here the modal dialog gets the datacontext from the DialogModel property of the Customer viewmodel, and binds commands and message. It would be also bound to some other element (here 'content') that needs to be disabled when the dialog shows (binding to IsShown). When you click some button in the dialog the associated command is called that simply calls the associated action that was passed in the constructor of the viewmodel.
This way I would be able to call Show() and Hide() of the dialog on the dialog viewmodel from inside the Customer viewmodel and alter the dialog viewmodel as needed.
It would give me only one dialog at a time but that is fine. I also think that the dialog viewmodel would remain unittestable, since the unittests would cover the calling of the commands that ought to be created after it being created with Actions in the constructor. There would be a few lines of codebehind for the dialog view, but very little and pretty dumb (setters getters, with almost no code).
What concerns me is:
Is this ok? Are there any problems I could get into? Does this break some MVVM principles?
Thanks a lot!
EDIT: I posted my complete solution so you can have a better look. Any architectural comments welcome. If you see some syntax that can be corrected the post is flagged as community wiki.
Well not exactly an answer to my question, but here is the result of doing this dialog, complete with code so you can use it if you wish - free as in free speech and beer:
XAML Usage in another view (here CustomerView):
Triggering from parent ViewModel (here CustomerViewModel):
Here is the code:
ModalDialogView XAML:
ModalDialogView code behind:
ModalDialogViewModel:
ViewModelBase has :
public virtual string DisplayName { get; protected set; }
and implements
INotifyPropertyChanged
Some resources to put in the resource dictionary:
I would approach this as a service that gets injected into your ViewModel, along the lines of the sample code below. To the extent what you want to do is in fact message box behavior, I would have my service implementation use a MessageBox!
I am using KISS here in order to present the concept. No code behind, and completely unit testable as shown.
As an aside, that Josh Smith example you are working off of was incredibly helpful to me also, even if it doesn't cover everything
HTH,
Berry
I have a custom open source
FrameworkElement
on my GitHub page that allows you to display modal content over the primary content.The control can be used like this:
Features:
IsModal
property.