Pregunta

Antecedentes: Estoy creando una aplicación de WPF usando MVVM, y el uso de un contenedor DI para construir mis ViewModels

Mi App.xaml se ve así:

<Application x:Class="WpfApp.App"
    ...xmlns etc...
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <app:ServiceLocator x:Key="serviceLocator" />
    </Application.Resources>
</Application>

MainWindow.xaml se parece a esto:

<Window x:Class="CompositeMefWpfApp.MainWindow"
    ...xmlns etc... >
    <Control.DataContext>
        <Binding Path="MainWindowViewModel" Source="{StaticResource serviceLocator}" />
    </Control.DataContext>

Ahora, todo esto funciona bien, pero el StartupUri está codificada en el XAML, que no quiero.
Siguiendo la orientación de varias entradas del blog y artículos que he encontrado, me quita el StartupUri, y trató de crear el MainWindow enganchando OnStartup en App.xaml.cs, como esto:

protected override void OnStartup( StartupEventArgs e )
{
    base.OnStartup(e);
    new MainWindow().Show();
}

El problema es, la aplicación se bloquea al intentar mostrar la ventana, con esta excepción:

  

No se puede encontrar el recurso llamado '{} ServiceLocator'. nombres de recursos entre mayúsculas y minúsculas. Error en el objeto 'System.Windows.Data.Binding' en el archivo de anotación 'WpfApp; componente / MainWindow.xaml'. La línea 8 Posición 45

Por lo que yo puedo decir, la sección <Application.Resources> simplemente no está siendo leído fuera del archivo XAML. Puedo poner un poco de código en el OnStartup añadir el recurso programáticamente como esto:

Resources.BeginInit();
Resources.Add("serviceLocator", new ServiceLocator());
Resources.EndInit();

Sin embargo eso es un truco feo, y no me ayuda si quería poner algo más en el archivo App.xaml más adelante: - (

¿Debo estar enganchando algún otro evento? ¿Hay una manera de evitar esto?

¿Fue útil?

Solución

En lugar de anular OnStartup, intente utilizar un evento en su lugar:

<Application x:Class="My.App"
    xmlns="..."
    Startup="Application_Startup"
    ShutdownMode="OnExplicitShutdown">
        <Application.Resources>
            <app:ServiceLocator x:Key="serviceLocator" />
        </Application.Resources>
    </Application>

Código atrás:

public partial class App : Application
{
    public App()
    { }
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // TODO: Parse commandline arguments and other startup work 
        new MainWindow().Show();
    }
}

Otros consejos

El más sencilla solución es la definición de un x: Nombre

<Application x:Name="App" ...
    <Application.Resources>
        ...
    </Application.Resources>
</Application>

Más información: http://connect.microsoft.com/VisualStudio/feedback/details/472729/wpf-cannot-find-resource-defined-in-the-app-xaml-file

Me he encontrado con un problema similar este mismo /. Hay un insecto generación de código VS en el que el código necesario para conectar <Application.Resources> al resto del programa veces no se inserta cuando <Application.Resources> contiene una sola entrada y no tiene un atributo StartupUri.

detalles: http://bengribaudo.com/blog / 2010/08/19/106 / fallo de un solo-Application-recursos-entrada-ignorado (disclaimer - enlace apunta a mi blog)

Para evitar este error conocimientos también se puede simplemente añadir recursos mediante programación.

var rd = new ResourceDictionary()
rd.Source = new Uri("pack://application:,,,/Resources;component/Colors.xaml");
Resources.MergedDictionaries.Add(rd);

Este código se puede colocar dentro de la construtor para la clase App.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top