c# .net wpf user-controls dispose

c# - Desechar los controles de usuario de WPF



.net user-controls (6)

Interesante entrada de blog aquí:

http://geekswithblogs.net/cskardon/archive/2008/06/23/dispose-of-a-wpf-usercontrol-ish.aspx

Menciona la suscripción a Dispatcher_ShutDownStarted para disponer de sus recursos.

Creé un control de usuario WPF personalizado que está destinado a ser utilizado por un tercero. Mi control tiene un miembro privado que es desechable, y me gustaría asegurar que siempre se llame a su método de eliminación una vez que se cierre la ventana / aplicación que lo contiene. Sin embargo, UserControl no es desechable. Intenté implementar la interfaz IDisposable y suscribirme al evento descargado, pero ninguno se llama cuando la aplicación anfitriona se cierra. Si es posible, no quiero depender de los consumidores de mi control que recuerden llamar a un método específico de Disposición.

public partial class MyWpfControl : UserControl { SomeDisposableObject x; // where does this code go? void Somewhere() { if (x != null) { x.Dispose(); x = null; } } }

La única solución que he encontrado hasta ahora es suscribirme al evento ShutdownStarted del Dispatcher. ¿Es este un enfoque razonable?

this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;


Mi escenario es un poco diferente, pero la intención es la misma. Me gustaría saber cuándo se cierra / cierra la ventana principal que aloja mi control de usuario, ya que la vista (es decir, mi control de usuario) debe invocar a los presentadores en closeView para ejecutar algunas funciones y realizar tareas de limpieza. (Bueno, estamos implementando un patrón MVP en una aplicación PRISM de WPF).

Me di cuenta de que en el evento Loaded del usercontrol, puedo conectar mi método ParentWindowClosing al evento Parent closing Closing. ¡De esta manera, mi Usercontrol puede estar al tanto cuando la ventana principal se cierra y actúa en consecuencia!


Tienes que tener cuidado con el destructor. Esto se invocará en el hilo del Finalizador de GC. En algunos casos, los recursos que su liberación pueden no gustar se liberan en un hilo diferente del que se crearon.


Un UserControl tiene un Destructor, ¿por qué no lo usas?

~MyWpfControl() { // Dispose of any Disposable items here }


Uso el siguiente Comportamiento de interactividad para proporcionar un evento de descarga a WPF UserControls. Puede incluir el comportamiento en UserControls XAML. Para que pueda tener la funcionalidad sin colocar la lógica en cada UserControl.

Declaración XAML:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" <i:Interaction.Behaviors> <behaviors:UserControlSupportsUnloadingEventBehavior UserControlClosing="UserControlClosingHandler" /> </i:Interaction.Behaviors>

Manejador de CodeBehind:

private void UserControlClosingHandler(object sender, EventArgs e) { // to unloading stuff here }

Código de conducta:

/// <summary> /// This behavior raises an event when the containing window of a <see cref="UserControl"/> is closing. /// </summary> public class UserControlSupportsUnloadingEventBehavior : System.Windows.Interactivity.Behavior<UserControl> { protected override void OnAttached() { AssociatedObject.Loaded += UserControlLoadedHandler; } protected override void OnDetaching() { AssociatedObject.Loaded -= UserControlLoadedHandler; var window = Window.GetWindow(AssociatedObject); if (window != null) window.Closing -= WindowClosingHandler; } /// <summary> /// Registers to the containing windows Closing event when the UserControl is loaded. /// </summary> private void UserControlLoadedHandler(object sender, RoutedEventArgs e) { var window = Window.GetWindow(AssociatedObject); if (window == null) throw new Exception( "The UserControl {0} is not contained within a Window. The UserControlSupportsUnloadingEventBehavior cannot be used." .FormatWith(AssociatedObject.GetType().Name)); window.Closing += WindowClosingHandler; } /// <summary> /// The containing window is closing, raise the UserControlClosing event. /// </summary> private void WindowClosingHandler(object sender, CancelEventArgs e) { OnUserControlClosing(); } /// <summary> /// This event will be raised when the containing window of the associated <see cref="UserControl"/> is closing. /// </summary> public event EventHandler UserControlClosing; protected virtual void OnUserControlClosing() { var handler = UserControlClosing; if (handler != null) handler(this, EventArgs.Empty); } }


Dispatcher.ShutdownStarted evento Dispatcher.ShutdownStarted se activa solo al final de la aplicación. Vale la pena llamar a la lógica de eliminación justo cuando el control deja de usarse. En particular, libera recursos cuando el control se usa muchas veces durante el tiempo de ejecución de la aplicación. Entonces, la solución de ioWint es preferible. Aquí está el código:

public MyWpfControl() { InitializeComponent(); Loaded += (s, e) => { // only at this point the control is ready Window.GetWindow(this) // get the parent window .Closing += (s1, e1) => Somewhere(); //disposing logic here }; }