Como usar o prism dentro de um elemento
Pergunta
Sou novo no Prism e estou tentando hospedar um controle prisimes em um elemento. Parece que estou faltando algo muito básico. Eu tenho um único winform que contém um elemento. O código a seguir está no formulário:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
var child = bootstrapper.Container.Resolve<Shell>();
elementHost.Child = child;
}
O Bootstrapper lida com a Regisration
public class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
Container.RegisterType<MyView>();
var shell = Container.Resolve<Shell>();
return shell;
}
protected override IModuleCatalog GetModuleCatalog()
{
ModuleCatalog catalog = new ModuleCatalog();
catalog.AddModule(typeof(MyModule));
return catalog;
}
}
O myview.xaml nada mais é do que um rótulo neste momento.
Shell.xaml é um UserControl que contém o seguinte xaml:
<ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion" />
O código do módulo é mínimo:
public class MyModule : IModule
{
private readonly IRegionViewRegistry _regionViewRegistry;
public MyModule(IRegionViewRegistry registry)
{
_regionViewRegistry = registry;
}
public void Initialize()
{
_regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(MyView));
}
}
Eu tenho rastreado profundamente o código Prism tentando descobrir por que a visão nunca é definida na região. Estou perdendo algo básico?
Solução
O motivo é este código em prisma:
private static bool RegionManager::IsInDesignMode(DependencyObject element)
{
// Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode.
return DesignerProperties.GetIsInDesignMode(element) || Application.Current == null
|| Application.Current.GetType() == typeof(Application);
}
O motivo é que, para o aplicativo não-WPF, o aplicativo.Current é nulo!
A solução:
- Crie uma classe vazia que herdará do System.Windows.Application. (Nome não importa):
No ponto de entrada para um plug-in, execute o seguinte código:
public class MyApp : System.Windows.Application
{
}
if (System.Windows.Application.Current == null)
{
// create the Application object
new MyApp();
}
É isso - agora você tem um aplicativo.
Outras dicas
@Mark Lindell acima funcionou para mim. As únicas coisas que tive que mudar estão abaixo.
Meu bootstrapper
public class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return this.Container.Resolve<Shell>();
}
protected override void InitializeShell()
{
base.InitializeShell();
if (System.Windows.Application.Current == null)
{
// create the Application object
new HelloWorld.Myapp();
}
//App.Current.MainWindow = (Window)this.Shell;
//App.Current.MainWindow.Show();
//MainWindow = (Window)this.Shell;
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
}
e minha aula de formulário
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Create the ElementHost control for hosting the WPF UserControl
ElementHost host = new ElementHost();
host.Dock = DockStyle.Fill;
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run(true);
//var uc = bootstrapper.Container.Resolve<Shell>(); This line threw error
//Create the WPF UserControl.
HelloWorld.Shell uc = new HelloWorld.Shell();
//Assign the WPF UserControl to the ElementHost control's Child property.
host.Child = uc;
//Add the ElementHost control to the form's collection of child controls.
this.Controls.Add(host);
}
}
}
E apenas para ficar claro, adicionei abaixo a classe no aplicativo WPF Prism contendo shell.
public class MyApp : System.Windows.Application
{
}
Editar: Observe que o manipulador de métodos de carga (do formulário) deve ser criado clique com a direita, na janela Propriedades, vá para eventos e dupla carga clicl. Copiar e colar o manipulador de eventos de carga não funciona.