2010-03-25 8 views
14

Así que mi llamada al método InitializeComponent en el constructor de la ventana se ejecuta a través del XML y agrega los controles y los conecta en sus eventos.Obtención de WPF referencia de control nulo durante InitializeComponent

Así que cuando una propiedad de uno de los controles cambia lo llama al Método que se suscribe al evento. El método hace referencia a un control que aún no se ha creado.

¿Por qué sucede esto en este orden aquí? Funcionó en WinForms porque los eventos no se activaron hasta más tarde, después de que se crearon todos los controles. ¿Hay alguna manera de forzar esto en WPF?

Las otras soluciones que veo son

  • necesito para suscribirse a los eventos después de la inicialización.

  • Necesito comprobar nulo cada vez que trato con un control.

+0

Sería útil saber específicamente qué eventos están causando el problema. ¿Puede agregar un poco más de detalle? Sin embargo, sospecho que la respuesta puede ser su primer punto ... –

+0

¿Puede explicarme más sobre la arquitectura? Tengo curiosidad por saber por qué una propiedad contendría la suscripción al evento. –

Respuesta

23

Acabo de tener este problema también, y lo resolví envolviendo la línea que accede al control nulo en una comprobación nula. Esto parece una especie de solución de hackeo.

Creo que WPF intenta ser útil llamando a nuestro evento Checked durante InitializeComponent(), en un esfuerzo por garantizar que cualquier lógica de UI (por ejemplo, mostrar/ocultar componentes relacionados) se ejecute en función del estado inicial de la casilla . Probé desactivando la casilla de verificación de forma predeterminada, y no se llama al controlador de eventos, aunque lo tengo conectado tanto a los eventos seleccionados como a los no registrados. Incluso reproduje esto en un proyecto WPF en blanco con una sola casilla de verificación en la pantalla, y se comporta igual.

El problema con este comportamiento predeterminado es, obviamente, que algunos de los otros componentes aún no se han inicializado. Creo que WPF debería esperar hasta que se hayan inicializado todos los componentes antes de activar el evento Checked de forma predeterminada.Esto podría no ser considerado un error, pero agregaré una nota a la página de MSDN relevante de todos modos ...

0

¿Alguno de los controles utiliza el enlace de datos bidireccional? Me encontré con este problema donde tuve textboxes vinculados a las propiedades en un ViewModel. La inicialización de ViewModel desencadenaba INotifyPropertyChanged hasta el control dependiente, lo que a su vez provocaba que el evento TextChanged del cuadro de texto se disparara. Mi solución a corto plazo fue mover la suscripción al evento de ventana cargada, pero como usted dice, eso es un poco molesto. Necesito refactorizar el código para cambiar el orden en cómo se inicializan mis objetos, de modo que las Vistas WPF (es decir, ventanas y controles de usuario) se creen antes de ViewModels. Luego, podré volver a mover el registro del controlador de eventos a XAML.

+0

No estoy utilizando ningún enlace de datos en tiempo de compilación. – rediVider

4

Debería poder comprobar las propiedades IsInitialized o IsLoaded en su ventana para verificar que haya terminado de inicializar/cargar. De lo contrario, necesitaría verificar nulo o agregar sus suscripciones de eventos en su código detrás (después de InitializeComponent).

Además, es posible que pueda ajustar la forma de acceder a los elementos. Por ejemplo, si tiene algo como:

<ListBox x:Name="listBox" SelectionChanged="OnListBoxSelectionChanged" /> 

Luego, en su código detrás se puede obtener el cuadro de lista de varias maneras:

private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { 
    ListBox lb = this.listBox; // May be null 
    ListBox lb = sender as ListBox; // Should never be null 
    ListBox lb = e.Source as ListBox; // Same as sender in this case 
    ListBox lb = e.OriginalSource as ListBox; // Always the element that started the event (if handler is not attached directly to ListBox). 
    // ... Do Something ... 
} 
+0

Tengo una forma ocupada con constante en/dis-abling. Supongo que tendré que mover las suscripciones de eventos al constructor después de que se ejecute init. – rediVider

5

Fue el caso de comprobarse con el botón de radio. Cuando eliminé Checked = "true" del xaml, el problema desapareció. (aunque está marcado cuando se inicia la ventana). No estoy seguro de lo que está pasando aquí, pero al menos no tuve que cambiar nada importante para arreglarlo ... todavía.

+0

Gracias rediVider, su solución funcionó para mí (estaba usando .NET 4.5.1). –

0

El control de la ventana activa los eventos controlados al inicializar los controles secundarios que se pueden verificar y se configuran como marcados como iniciales valor.

Soy de la opinión de que esto es un error. Solo el hecho de que dispara una NullReferenceException desde lo profundo del ensamblaje de MFC debería ser suficiente para esperar que este sea un comportamiento no deseado.

Considerando que el editor Xaml crea funciones de controlador dentro de su clase parcial de Control y si esta clase no se termina de construir, no puede manejar eventos. No creo que disparar un evento marcado para controlar tu configuración, desde inicializado hasta marcado, parezca correcto.

Es decir, ¿debería activarse un evento Desmarcado si configura su estado inicial para desmarcarse?

1

Tuve el mismo problema y creo que es un error. Encontré una solución: Quité el 'Ischecked' de Xaml y lo configuré en el código detrás de init

Cuestiones relacionadas