Hi Mark,
This one will be interesting to make work.
Magellan controllers are typically written like this:
public ActionResult Get(int customerId)
{
Model = GetCustomer(customerId);
return View();
}
Magellan instantiates the view, and also sets the view's data context to the model.
However, your MVVM framework uses a markup extension to connect events on the VM to closing and activating the window. Your extension does two things - it instantiates the model, and it connects it to the window.
The workaround for me would be to write a custom View Engine that when opening a Window, instead of setting the datacontext directly, it uses your markup extension to set it. The problem there is your markup extension wants to create the VM - I can't just give it the one from the controller.
I can probably take some of the code from the markup extension that does the wiring up for the window and just replicate it in the custom Magellan view engine. It would look something like this:
public class JulmarWindowViewEngine : UIElementViewEngine
{
private readonly IViewActivator _viewActivator;
public JulmarWindowViewEngine(IViewActivator viewActivator) : base("", "View", "Window", "Dialog", "ViewWindow", "ViewDialog")
{
_viewActivator = viewActivator;
}
protected override IEnumerable<Type> FilterCandidateTypes(ControllerContext controllerContext, ParameterValueDictionary viewParameters, string viewName, IEnumerable<Type> candidates)
{
return candidates.Where(type => typeof (Window).IsAssignableFrom(type));
}
protected override ViewEngineResult CreateViewResult(ControllerContext controllerContext, ParameterValueDictionary viewParameters, Type type)
{
return new JulmarWindowViewEngineResult(controllerContext, viewParameters, type, _viewActivator);
}
}
public class JulmarWindowViewEngineResult : ViewEngineResult
{
private readonly ControllerContext _controllerContext;
private readonly ParameterValueDictionary _viewParameters;
private readonly Type _viewType;
private readonly IViewActivator _viewActivator;
public WindowViewEngineResult(ControllerContext controllerContext, ParameterValueDictionary viewParameters, Type viewType, IViewActivator viewActivator)
: base(true, new string[0])
{
_controllerContext = controllerContext;
_viewParameters = viewParameters;
_viewType = viewType;
_viewActivator = viewActivator;
}
public override void Render()
{
var instance = (Window)_viewActivator.Instantiate(_viewType);
if (_viewParameters.ContainsKey("Model"))
{
var model = _viewParameters["Model"];
if (instance is IView) ((IView)instance).Model = model;
else instance.DataContext = model;
// Copied and pasted from ViewModelCreatorExtension.cs
var jvm = model as JulMar.Windows.Mvvm.ViewModel; if (jvm != null)
{ jvm.CloseRequest += ((s, e) =>
{ try
{ winTarget.DialogResult = e.Result;
} catch (InvalidOperationException)
{ // Raised if this was displayed via Show() vs. ShowDialog
winTarget.Close(); }
}); jvm.ActivateRequest += ((s, e) => winTarget.Activate());
} }
instance.Show();
}
}
It's a shame to have to replicate this code though. What do you think?
Paul
--
Paul Stovell