PRISM + MVVM + MEF + ChildWindow + SL4

Topics: Prism v4 - Silverlight 4
Oct 21, 2010 at 1:04 PM

Can anyone please let me know how to define region in ChildWindow and navigate/inject view into it displaying a modal popup. This should also compose the view using MEF to import is corresponding ViewModel and other imports like IEventAggregator.

A prompt response with sample application will be greatly appreciated.

Thanks,

Milind

Oct 21, 2010 at 4:21 PM

reference the SL version of the stocktrader_ri. In the shell notice the top of the shell there is xaml code for the "SecondaryRegion" this is directly related to the ChildWindow control in silverlight.   In wpf I use standard region methodology to get to it. To understand what is going on the code that makes all this happen is in the Infrastructure project under behaviors.

 

regionManager.Regions["SecondaryRegion"].Add(someView);

this is done in your bound button/link with Commanding.

regionManager.Regions["SecondaryRegion"].Activate(someView);

or

regionManager.RequestNavigate("SecondaryRegion", new Uri("/theviewinquestion", UriKind.Relative));

When I want to indicate the window is closing I use regionManager.Regions["SecondaryRegion"].Deactivate(someView); which is called via a ICommand bound to a button.

 

    xmlns:infBehaviors="clr-namespace:StockTraderRI.Infrastructure.Behaviors;assembly=StockTraderRI.Infrastructure"
    infBehaviors:RegionPopupBehaviors.CreatePopupRegionWithName="SecondaryRegion"
    infBehaviors:RegionPopupBehaviors.ContainerWindowStyle="{StaticResource PopupStyle}">

Oct 26, 2010 at 9:05 AM

Thanks for the reply, can you please clarify following.

when you are saying  "the top of the shell there is xaml code for the "SecondaryRegion" this is directly related to the ChildWindow control in silverlight" do you mean it is derived from ChildWindow class? Besides this how do you get the instances of view to Add or remove or activate using regionManager.Regions["SecondaryRegion"].Add/REmove/Activate(someView);

I have one more query how to create object isntances using MEF explicitly so that object getting created wtill import all its dependency. How can I get hold of MEF container from within code. I know we can get it in the bootstrapper, but I am looking for it in the modules so that I can compose my view using MEF ( so that all dependencies like ViewModel, IEventAggregator etc get imported). Waiting for your response.

It would be great if some one can help me getting ChildWindow scenatio working with some example or sample app.

Milind

 

Oct 26, 2010 at 4:39 PM
Edited Oct 26, 2010 at 5:39 PM

at the bottom of my post there is the code fragment that is facilitating the popup window.  In wpf I am using this feature now.  The wpf code base uses Windows and SL code base uses ChildWindow class (which is part of silverlight, but not in wpf bcl).  Farret thru that xaml markup and see then also reference the Infrastructure and look for the Behaviors.

As for activating use the newer regionManager.RequestNavigate("SecondaryRegion", new Uri("/theviewinquestion", UriKind.Relative)); 

then I use

var viewinquestion = regionManager.Regions["SecondaryRegion"].GetView("viewinquestion");  <<-- since Deactivate takes an object parameter.
regionManager.Regions["SecondaryRegion"].Deactivate(viewinquestion);

for closing the popup window.

Oct 26, 2010 at 6:21 PM

I am also very interested in this solution,

but also could not understand the code you posted.

I took a loke at the StockTraderRI and could not understand that too. and its not a popup.

Is there another simple example? 

Oct 27, 2010 at 4:06 AM

Can you please send me the working sample. I know StockTickerRI is there but it has too many things...I just want to clarify the concepts of modal popup display using PRISM mechanism. How easy it is for everyone to stard adding popup, sending data back to parent screen, hiding popup, sharing popup between different modules etc.

I hope you will come up with the satisfactory answers as you have already...

Most important one is behaviour concepts, what are they?

Milind

Oct 27, 2010 at 1:33 PM
Edited Oct 27, 2010 at 1:41 PM

Ok guys I will post a solution, it uses a region for the popup (aka modal dialog).  I have modified the behavior that StockTraderRI uses to show as a dialog not as "non-modal dialog".  The code should work for silverlight but since I don't use SL atm, I haven't tested it under SL.  N.B. I have't modified the code for SL. 

Give me a few and I will post a very functionally slim example for ya to look thru... As for bringing data in and out, I will leave that for drill since it isn't that hard.

Morgan.

Oct 28, 2010 at 4:13 AM

Thanks Morgan, really appreciated...waiting for the source code. I hope you will be uploading it to some shareware sitte for downloading. I also don't mind the non modal version of the popup behaviour just to have a look at it. But most important one is modal popup behaviour with MVVM pattern ( wher MEF composes all of view, viewmodles parts). Thanks again, it will really help me in understanding the behaviour and regions.

Thanks,

Milind

Oct 28, 2010 at 2:45 PM
Edited Oct 28, 2010 at 2:46 PM

Waiting for the source code too.

i have found a solution to use ChildWindows, but i think its not a Elegant Solution:

My App:

  • App (Main Project)
  • ModuleA
    • ViewA
    • ChildWindowA
  • ModuleB
    • ViewB
    • ChildWindowB (that needs to call the ChildWindowA)
  • Lib (Silverlight Library Project)

So, in the Lib project a declared an Interface:

 

public interface IChildWindowA
{
   void Show(/* pass ViewModal and Current Record to update*/);
}

 

in the ChildWindowA, implements the Interface

 

[Export(typeof(IChildWindowA))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class EditTemp : ChildWindow, IChildWindowA
{
   public void Show(...)
   {
      this.Show();
   }
}

 

The ModuleB DependsOn the ModuleA, In a Button Click inside the ChildWindowB in the ModuleB:

 

private void OnButtonClick(object sender, RoutedEventArgs e)
{
   _editWindowA = (IChildWindowA)ServiceLocator.Current.GetInstance(typeof(IChildWindowA));
   _editWindow.Show(...);
}

Is that a Bad Solution? or i can go with that

 

 

Oct 28, 2010 at 3:21 PM
Edited Oct 28, 2010 at 3:30 PM

http://cid-c9472b51c27dc8fe.office.live.com/browse.aspx/.Public

copy / paste that link to my skydrive and then download the .zip with the solution in it...  Don't forget to "unblock" if you have anti-viral in place.   This is guidance is based on the StockTrader implementation.  It's rough and could probably be refined and allow for a better solution for editing but they way I do it in my other project is check for an object is null if is then its a new entry and vice-versa if its not null then its an edit.  I am merely setting an object of type x (where x is the record) to the most current selection and going from there, edit/delete, etc...  That object is in the viewmodel.

The contracts for simplicity sake are not concrete, which can be changed to interfaces for extensibility purposes.

In the Behaviors folder are all the files that StockTrader use to make a "SL Popup" or a WPF Window.

Oct 28, 2010 at 5:37 PM

Thx alot mvermef,

But i have a consideration:

In the Module inizialization, you imported the and added the view to the Region (Popup). Thats a problem im my App, becausa my App have alot of Popups, and i think its a problem create all and add to the region in the initialization of the module.

I made some changes in your example to try to solve this potential problem.

1 - In the Module initialization i removed the code that Add the view to the region:

    [ModuleExport(typeof(ExampleModule))]
    public class ExampleModule : IModule
    {
        private IRegionManager regionManager;

        //import the view and create a new instance.
        //[Import]
        //private DemoView view { get; set; }

        [ImportingConstructor]
        public ExampleModule(IRegionManager regionManager)
        {
            this.regionManager = regionManager;
        }


        public void Initialize()
        {
            //register the view with the region.
            //regionManager.Regions["SecondaryRegion"].Add(view, "DemoAppView");
        }
    }

2 - Created an Interface to export the view:

namespace DemoApp.Infrastructure
{
    public interface IDemoView
    {
    }
}
    [Export(typeof(IDemoView))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    [RegionMemberLifetime(KeepAlive = false)]
    public partial class DemoView : UserControl, IDemoView
    { ... }

3 - At the Command that who the Modal Window:

    public void ShowModalWindow()
        {
            regionManager.Regions["SecondaryRegion"].Add(ServiceLocator.Current.GetInstance<IDemoView>(), "DemoAppView");
            regionManager.RequestNavigate("SecondaryRegion", new Uri("/DemoView", UriKind.Relative));
        }

4 - I have a problem in the Close button of the view, the have that attribute "[RegionMemberLifetime(KeepAlive = false)]", but i think its not working, because when i Deactivate the View, its still alive and are not destroyed s. So i removed the view.

        private void Close()
        {
            //Get the View
            var view = regionManager.Regions["SecondaryRegion"].GetView("DemoAppView");

            //Not Found fail gracefully, otherwise closes the view/region
            if (view != null)
            {
                regionManager.Regions["SecondaryRegion"].Deactivate(view);
                regionManager.Regions["SecondaryRegion"].Remove(view);
            }
        }

How do think about the sollution? I Just need to Declare and implement an interface for each of the Modals in my Application.

 

Heres the updated Demo App: http://cid-59bcdc091895608b.office.live.com/self.aspx/P%C3%BAblica/DemoApp.zip

Oct 28, 2010 at 9:09 PM
Edited Oct 28, 2010 at 9:10 PM

 

All are probably good suggestions, like I said it was a rough app and there is always room for improvement.  When i said I would post a solution I was at a conference and then later waiting to catcha  flight out of DC, i threw the bulk of the demo together then finished it today.  But I think you get the general idea, I hope it helped.  I hadn't ever thought of using the ServerLocator that way since I was using MEF to the majority of the work.  I might have to use the locator more to get stuff into the regions like you had there.

 

Morgan.

Oct 28, 2010 at 10:40 PM

But isnt that a bug?

If my view has: "[RegionMemberLifetime(KeepAlive = false)]" that code should destroy the view " regionManager.Regions["SecondaryRegion"].Deactivate(view);", but the view are not destroyed.. so i need to Remove that from the view.

 

Oct 29, 2010 at 1:49 AM

Its either that or we aren't disposing correctly of the view on close.

Nov 10, 2010 at 4:39 AM

Thanks guys for good suggestion and solutions...but can anyone confirm the approach for opening one modal popup in Module B from modal popup in Module A lanucnhed from the view within module A. It would be great to have ddemo solution as above. There will be often scenation where you common modal popups such as serach screens will be in the common module which will get called from other modules . Besides this when  we use WCF RIA services  it geenrates entites on the client side whcih can be shared and used by other modules. My question here is from deployment prospective how will be able to acheive deployment of only module A which resulting in to changes in common entities used by other modules lets say module B and C, Do I have to build this module as well and deploy them as they are using entities changed due to changes in Module A. I want a strategy where I will be able to deeply only parts that got changed

A good guidance on achieving modularity from deployment prospective is all I need here in the production environment and version management.

Nov 10, 2010 at 3:23 PM
Edited Nov 10, 2010 at 3:33 PM

milind_yande,

yes this will do what we are suggesting.  as long as the module is initialized and it good working order this can be achieved.  I would even go as far as saying it would be a good idea to even make the modules dependent on one or the other.  I gather that module b is depending on module A in some fashion so there you go.  The example above would work.  It might even be necessary for a IEventAggregator to be used to do cross module event calls e.g. showing the dialog.

 

Morgan.

Nov 15, 2010 at 6:59 AM

Thanks Morgan, it would be good if you can post a sample demonstrating cross module calls for launching popup from within popup. I hope there is one sample already to which I can refer.

Waiting for your resppnse..this will save us lo of time as there is deadline...hoping for the best.

Milind

 

Feb 10, 2011 at 6:49 AM

OK so I can get the example simple demo app provided earlier in this post to work.  However, when I apply this to my solution, the window that pops up is not modal, and I really can't figure out why this is.  With the popup window open, I can still interact with the parent window.

Any pointers as to where I need to look to ensure that my app opens the window as modal?

Feb 10, 2011 at 11:19 AM

Nevermind, I found it.  Turns out I had to change the implementation of the Show method in the WindowWrapper class.

Feb 10, 2011 at 2:57 PM

yea I had to modify the underlying code in that class to make it modal..

Feb 16, 2011 at 12:26 AM

With lucianotcorreia example, what do you do if the user closes the window an alternate way other than the 'close' button?

Example.
Click button to open popup, then Alt+F4 or the x button, then click open popup. An exception occurs when trying to add 'DemoAppView' to the region.

I can add validation code to the ShowModalWindow, but I rather not do that for every viewmodel popup.

Any suggestions?

Jun 6, 2011 at 11:00 AM

I can confirm xiquon is correct - if you close the modal using Alt + F4 an exception occurs. Are there any suggestions?