Using a Prism in a class library project

Topics: Prism v4 - WPF 4
Nov 16, 2011 at 1:03 AM

Similar to this post http://social.msdn.microsoft.com/Forums/en/wpf/thread/d10de84c-bef1-46ed-8127-7ad19b8eec37

I have finally worked out how to load WPF window from a class library as needed for a Addin application I'm building.

Now I'd like to use Prism however I'm not sure how to show the shell via the bootstrapper.

eg for running outside the addin (dll) I change from class to windows application so i need to launch the shell / bootstrapper form the static class Program > Main() entry point.

Is this possible? How?

 

Thanks.

Nov 16, 2011 at 6:06 AM
        protected override DependencyObject CreateShell()
        {
Window win = loaded-from-your-dll;

            Application.Current.RootVisual = win;

            return win;
        }
Nov 16, 2011 at 10:35 AM
Edited Nov 16, 2011 at 10:38 AM

Thanks but I'm still lost on this 1... Im not sure what code to put in "loaded-from-your-dll; value? RootVisual is not part of Application.Current... http://stackoverflow.com/questions/2216917/wpf-equivalent-to-silverlight-rootvisual

and where the Bootstrapper runs from... I tried may things and could not make it work...

Maybe you could advise how I can change rthe code I have that is working in WPF app just not from windows or a dll:

 

 static class Program
    {
        [STAThread]
        static void Main()
        {
		// entry point to run from
        }
    }
 

Bootstrapper?

 public class Bootstrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return Container.Resolve();
        }


        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.MainWindow = (Window)Shell;
            Application.Current.MainWindow.Show();
        }

        protected override void ConfigureModuleCatalog()
        {
            base.ConfigureModuleCatalog();

            var moduleCatalog = (ModuleCatalog)ModuleCatalog;
            moduleCatalog.AddModule(typeof(FamilyBrowserModule));
        }

    }

 App.xaml.cs
 
public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }
    }
 
Thanks 

 

Developer
Nov 16, 2011 at 5:04 PM
Edited Nov 16, 2011 at 5:06 PM

Hi,

Based on my understanding, in WPF you can show a Window in the Main method using the following code:

[STAThread]
public static void Main()
{
      Application app = new Application();
      Window myWindow = new Window();
      myWindow.Show();
      app.Run(myWindow);
}

Knowing this, you might be possible that you could use a bootstrapper, for example, creating a property in your Bootstrapper class that accepts an Application object and in the InitializeShell method show the Shell like above:

[STAThread]
public static void Main()
{
      Application app = new Application();
      MyBootstrapper bootstrapper = new MyBootstrapper();
      bootstrapper.CurrentApplication = app;
      bootstrapper.Run();
}

...

protected override void InitializeShell()
{
      base.InitializeShell();

      if( this.CurrentApplication != null )
      {
            Window shell = this.Shell as Window;
            shell.Show();
            this.CurrentApplication.Run(shell);
      }
}

(Note: We have not tested this code and we cannot guarantee that it won't cause an unexpected behavior in your application)

However, the implementation details depends mostly of your personal preferences and the requirements of your scenario.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Nov 17, 2011 at 7:52 AM

Hey Damian, thanks getting a bit closer with this...

The following does not get to the Module for regionManager etc

 

protected override void InitializeShell()
{
      base.InitializeShell();

      if( this.CurrentApplication != null )
      {
            Window shell = this.Shell as Window;
            shell.Show();
            this.CurrentApplication.Run(shell);
      }
}

 

I tried the following which makes it to regionManager and shows the window however the Region is not injected into the view. Any ideas

 

 protected override void InitializeShell()
        {
            base.InitializeShell();

            if (CurrentApplication != null)
            {
                
                CurrentApplication.MainWindow = (Window)Shell;
                CurrentApplication.MainWindow.ShowDialog();
            }
        }

 

Maybe something needs to happen in the App OnStartup as the Bootstrapper cannot run from here...?

 

 

 public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            //Bootstrapper bootstrapper = new Bootstrapper();
            //bootstrapper.Run();
        }
    }

Any help appreciated. Thanks.

 

Developer
Nov 17, 2011 at 8:52 PM

Hi,

We were able to run the HelloWorld QuickStart from a Console Application project following these steps:

  • Open the HelloWorld QuickStart and create a new Console Application project.
  • In this project add a reference to the following dlls: WindowsBase.dll, System.Xaml.dll and PresentationFramework.dll.
  • In the same project add a reference to the HelloWorld.Desktop project.
  • In the App.xaml.cs file of the HelloWorld.Desktop project, define the following method. This is done so that the Run method can be invoked in the Console Application project.
        new public int Run()
        {
            return base.Run();
        }
  • Define the Main method in the Console Application project like this, where App is the App class in the HelloWorld.Desktop project. However,
        [STAThread]
        static void Main(string[] args)
        {
            App application = new App();
            application.Run();
        }

Doing this, when the Run method is invoked the OnStartup method will be invoked too, which will instantiate and run the Bootstrapper.

Based on this you, you could implement you own approach for your scenario according to your requirements and preferences. However, take into account that as the host application is a Console Application, there might be some scenarios where the aforementioned approach could cause and undesired behavior in you application.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Nov 17, 2011 at 9:50 PM

I did try something similar however it would not run in Revit (the software I am creating the addin for) I think because the app was being run from a separate dll or domain maybe.

Prism is becoming a bit hard to use in the scenario I going to have a look at http://simplemvvmtoolkit.codeplex.com/