All, I would like to know the recognised best approach/industry standard of launching [child] dialogs/windows from an WPF using the MVVM pattern. I have come across the following articles:
A. CodeProject - Showing Dialogs When Using the MVVM Pattern
This approach seems good but excessive to me. The is some degree of code replication and I am not convinced this is the right way to go.
B. WPF MVVM and Showing Dialogs
This briefly runs through three options with various links which are all fairly/very poor at explaining the methodology or are of-topic.
Can someone please provide an explanation of the industry standard method/approach of launching dialogs from a WPF application using MVVM and preferably some links to further reading material? If you can provide an example yourself I would of course be most appreciative!
Thanks for your time.
First of all, i don't know of any "industry-standard" way for showing dialogs using MVVM because there is no such thing.
Secondly, Welcome to MVVM, you have just touched on of the areas that MVVM don't have a standard for.
To tell you the truth, MVVM has many pain points and this is the reason why there are tons of MVVM frameworks out there, just to mention a few MVVM Light, PRISM, Caliburn.Micro, Cinch, Catel, WAF, Baboon, shell i stop or you want more.
Now to answer your question and after dealing with most of those frameworks, i noticed one commonality, they all use a DI/IoC container and then provide you with an interface, something like IDialogManager and an implementation of their own, and then they ask you to accept this interface in your view model and use it to show dialogs. So to sum this up, i would use dependency injection, have an interface for showing dialogs, and then provide and implementation of that, and register it with the di container and then consume it from my view model or views.
Edit: So you have picked PRISM (which in my opinion) is hardest between them all in showing dialogs. Now that's aside, there is the hard way which is by using Interaction Requests (check the middle of the article), or you can use this Answer as a quicker way.
Recently, I've implemented my own Navigation Service for WPF, which uses Caliburn.Micro's WindowManager (but you could replace it by something else).
Example (how to use):
_navigationService.GetWindow<ClientDetailsViewModel>()
.WithParam(vm => vm.IsEditing, true)
.WithParam(vm => vm.Client, SelectedClient)
.DoIfSuccess(() => RefreshSelectedClient())
.ShowWindowModal();
Implementation:
namespace ClientApplication.Utilities
{
public class NavigationService : INavigationService
{
SimpleContainer _container;
IWindowManager _windowManager;
public NavigationService(SimpleContainer container, IWindowManager windowManager)
{
_container = container;
_windowManager = windowManager;
}
public INavigationService<TViewModel> GetWindow<TViewModel>()
{
return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
}
}
public class NavigationService<TVM> : INavigationService<TVM>
{
IWindowManager _windowManager;
TVM _viewModel;
System.Action _action;
public NavigationService(IWindowManager windowManager, TVM viewModel)
{
_windowManager = windowManager;
_viewModel = viewModel;
}
public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
{
var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
prop.SetValue(_viewModel, value, null);
return this;
}
public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
{
action(_viewModel);
return this;
}
public INavigationService<TVM> DoIfSuccess(System.Action action)
{
_action = action;
return this;
}
public void ShowWindow(IDictionary<string, object> settings = null)
{
_windowManager.ShowWindow(_viewModel, null, settings);
}
public bool ShowWindowModal(IDictionary<string, object> settings = null)
{
bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
if (result && _action != null)
_action();
return result;
}
}
}
Interfaces:
namespace Common
{
public interface INavigationService<TVM>
{
INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);
INavigationService<TVM> DoIfSuccess(System.Action action);
INavigationService<TVM> DoBeforeShow(Action<TVM> action);
void ShowWindow(IDictionary<string, object> settings = null);
bool ShowWindowModal(IDictionary<string, object> settings = null);
}
public interface INavigationService
{
INavigationService<TViewModel> GetWindow<TViewModel>();
}
}
The most recent release of Prism (download here) contains a so-called "Reference Implementation" of an MVVM application called "Stock Trader". My rationale was that if the Prism team is calling it a "Reference Implementation", that's the most "standard" from their point of view (if anything in MVVM is standard), and the logical choice to press on with.
The source contains an infrastructure library for raising modal dialogs, and it's pretty good. So I adopted that library and have deployed it successfully (I uploaded such an app to Codeplex).
I needed to tweak the code to 1 add the parent's icon to the title bar because the library didn't provide for it; and [2] add some meaningful text to the title bar because the library left it blank and [3] add a delegate to invoke when the dialog closes. It's abstracted to the extent that a VM can raise a dialog by passing two strings (i.e., the Unity Registration Names) to a mediator. Those changes are available on Codeplex.
So among all the other 'standards' the "Reference Implementation" should minimally participate as a viable choice. The more oblique answer to your question is that if your View Models are sufficiently isolated and work entirely through POCO interfaces, then in THEORY, it shouldn't matter because switching to another 'standard' should be a trivial exercise.
i simply use a dialogservice, see here
within your viewmodel you just have to do:
var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
... do anything with the dialog result...
Creating a dialog service has worked out well for me, and is also suggested in both your links.
Later I saw the same solution at the dev days in an MVVM presentation by Gill Cleeren. Check the link for working code samples (though written for Metro)
Only thing that nags me a bit about the dialog service is that it is in some way UI technology (rich client) dependent.
A simple request-response web frontend View can be built on top of the same ViewModel and Model code that the WPF XAML binds to. Until the ViewModel starts popping up dialogs through the dialog service. I would not know how to implement the dialog service for a web view. Implementing dialogs there would require pushing a bit more logic to the view.
Purpose of using interface to implement dialogs is to make code testable. In this case, "A" is widely used, but it is still hard to say "Standard". If you do not have test on your ViewModel or you can test your ViewModel avoid touching dialogs, such as using Extract-Override, you can definitely do not follow the instruction.
I am stating to look into the Domain Events pattern and have read a lot of resources on the subject but I cannot find a good way of implementing for our requirements. Basically we have a Service/Domain layer which wraps the repository layer for reads/writes with a simplistic CQRS implementation. We have an ASP.NET Mvc application which consumes this service/domain layer. The whole application is tied together with Autofac and what I would like to happen is for the following:
When a news item is created by calling say "CreateNews" on the service layer register that an event will need to be raised as so:
public void CreateNews(Domain.Entities.News.NewsBO news)
{
ValidateBusinessObject(news);
var entityNews = AutoMapper.Mapper.Map<Repositories.Entities.News.News>(news);
NewsCommandRepository.Create(entityNews);
_domainEventManager.Register<NewsCreatedDomainEvent>(x => x.News = news);
}
This is all happening in a transaction and I don't want to actually raise the event until the save is completed so in our save changes method I want to do this:
public void SaveChanges()
{
_repoCommandManager.SaveChanges();
_domainEventManager.RaiseEvents();
}
Then in our ASP.NET Mvc application I want to have an implementation of an IHandler which looks like this:
public class NewsCreatedDomainEventCacheHandler : IHandles<Project.Services.Domain.Events.News.NewsCreatedDomainEvent>
{
public void Handle(Services.Domain.Events.News.NewsCreatedDomainEvent #event)
{
// In here we would update the cache or something else particular to the web layer
}
}
I cannot figure out how to go about raising this event from the save method and calling the implementation in the Web.Mvc application.
Any suggestions would be appreciated.
I think I have an example of how to do this for you and I happen to be using MVC and AutoFac also! In my specific example I am concentrating on Command/Query separation but in doing so I had to implement a domain event pattern.
First have a read of this blog post so you get an overview of how things hang together and what the code looks like:
http://www.nootn.com.au/2013/03/command-query-separation-to-better.html
So I would recommend installing the DotNetAppStarterKit.Web.Mvc NuGet package, then take a look at the Global.asax file for how to register all the components you will need. You can peruse the SampleMvc application for things like Event Subscribers.
I hope this helps and gets you up and going quickly. You can just use the event publisher/subscriber parts of DotNetAppStarterKit without using commands and queries.
We are developing large MVC project and we have an intension to use HttpSessionStateWrapper (as well as HttpRequestWrapper, HttpResponseWrapper, etc) to add extended functionalities do this objects. It would be adding session messages, additional collections, html metadata with response - stuff like that, managable from controllers and accessible in the views when needed.
I have done it in a smaller project and it gennerally worked well, except some casting issues here and there, but it can be worked around by not using wrappers outside controllers or eventually views. Every controller would be a custom controller with a code like that:
public class Controller : System.Web.Mvc.Controller
{
public new CustomHttpResponse Response
{
get
{
return (CustomHttpResponse)HttpContext.Response;
}
}
public new CustomHttpRequestRequest
{
get
{
return (CustomHttpRequestRequest)HttpContext.Request;
}
}
//etc...
}
ContextWrapper would be created in a custom MvcHandler. Response, request and session wrappers would be created and taken from ContextWrapper .
Is this a good policy to use wrappers to extend functionalities, or they where intended only for creating testing mocks?
I'm working on a small school project, an ASP.NET C# website; we're working with a Web Application, using a Global.asax file to centralize request logic.
Anyway, my colleague and I are responsible for the coding in our group, and we both come as reasonably experienced PHP developers. We both rather enjoy working with the architectural style used by the PHP framework Laravel, using routes (callbacks associated with) as the "controllers", and (despite it being a square peg, round hole issue) are trying to replicate that functionality for this project.
This is no easy task; I've implemented the IRouteHandler interface as a CallbackRouteHandler in an attempt to start replicating this functionality:
public class CallbackRouteHandler : IRouteHandler
{
public Func<RequestContext, IHttpHandler> Callback { get; protected set; }
public CallbackRouteHandler(Func<RequestContext, IHttpHandler> callback)
{
this.Callback = callback;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return this.Callback(requestContext);
}
}
Unfortunately this is about as far as I've gotten. I'm reading through the ASP.NET Page Life Cycle Overview, attempting to understand better the entire process.
What we're stuck on is programmatically loading ASPX files (rather, instantiating as Page objects) in the scope of a given route callback. We were hoping there would be a reasonably easy way to accomplish, within the scope of the callback, something like:
// instantiate the target ASPX page object
OurSite.SomeNamespace.SomePage page = new OurSite.SomeNamespace.SomePage();
// manipulate the page object, setting public properties, etc.
page.SomeControl.Text = "Foobar!";
// eventually "render" the file to somehow; at this point, the
// page and it's associated code-behind events take control
page.Render();
I'm having trouble understanding both: 1) How to do this? 2) When (relative to the aforementioned page life-cycle) to do this.
How (if at all) can one accomplish this sort of functionality? I'm seeing that this process, hidden away by ASP.NET, is seemingly very complicated, but surely others have tread down this path before.
I went with MVC for this project, however I've since had the opportunity to dissect the ASP.NET request pipeline a bit, and have implemented custom routing solutions as warranted.
I am starting with MVC 3 and am planning in separating the model and the controllers into their own separate projects. I'll follow the suggestions made from this post for this:
asp.net mvc put controllers into a separate project
The purpose of separating them into separate projects is that there are chances that I may have to add a web service project to the solution and I’d like it to reuse the same functionality exposed by the controller project. So the solution will be formed of two view projects, WebServices and WebSite, the controller project and the model project.
I’d like to know if this is possible and if it’s a common scenario with MVC.
Update 1:
With your suggestions I agree and think it’s best to keep the view and the controllers together.
Would it be possible to have a hybrid of MVC and MVP? I have a feeling I am really overdoing things here so please let me know what you think.
So I would have:
1 – Web project with controllers.
2 – WebServices project
3 – Presenters/Interfaces.
4 – Model.
The controllers would then become the views in an MVP model. Also each web service would become a view in an MVP model.
For instance we could have the following, interface, presenter , controller.
public interface ICustomers {
string[] Customers{set;}
}
public class CustomerPresenter {
ICustomers view = null;
public CustomerPresenter(ICustomers view) {
this.view = view;
}
public void GetCustomers() {
view.Customers = new string[]{"Customer1","Customer2"};
}
}
public class CustomerController:ICustomers {
CustomerPresenter presenter = null;
public CustomerController() {
presenter = new CustomerPresenter(this);
}
private string[] customers = null;
public string[] Customers {
set { throw new NotImplementedException(); }
}
public void GetCustomers() {
presenter.GetCustomers();
//Return view.
}
}
The WebService would be a view in an MVP model.
public class CustomerWebService:ICustomers {
CustomerPresenter presenter = null;
public CustomerController() {
presenter = new CustomerPresenter(this);
}
[WebMethod]
public void GetCustomers() {
presenter.GetCustomers();
//Return response.
}
My projects are built specifically for the reason you stated, you want to implement a web service. I would not recommend separating the controllers because this is an actual part of the web project. What you actually want is around 3-4 different projects.
Repository/data layer (may contain your domain level models)
Domain Layer (optional)
Service layer. (Now this is where you can point your web service to very easily, all your re-usable logic should be here, not in the controller)
Web Layer. (Contains View Models, Views and Controllers)
I placed them in levels. Basically, the repository, domain and service layer are completely de-coupled, meaning you can use these libraries without a server or asp.net. A wpf application can just call to the service layer because the web layer is just for presentation purposes.
I am not sure it's common to separate the views and the controllers on their own projects. It might be but I haven't seen it personally.
The way I would split it initially is:
One project for views and controllers
One project for models
If and when you have the need to support different views you could update your controller to return something different depending on the type of request. It's common to have controllers that return different things for different clients (for example HTML vs JSON.)