处理WPF用户控件
我已经创build了一个自定义的WPF用户控件,这个控件可以被第三方使用。 我的控制有一个私人成员是一次性的,我想确保其处理方法将永远被调用一旦包含的窗口/应用程序closures。 但是,UserControl不是一次性的。 我尝试实现IDisposable接口并订阅Unloaded事件,但是在主机应用程序closures时不会调用。 如果可能的话,我不想依赖于我的控制的消费者记得调用一个特定的Dispose方法。
public partial class MyWpfControl : UserControl { SomeDisposableObject x; // where does this code go? void Somewhere() { if (x != null) { x.Dispose(); x = null; } } }
我目前find的唯一解决scheme是订阅Dispatcher的ShutdownStarted事件。 这是一个合理的方法吗?
this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
这里有趣的博客文章:
http://geekswithblogs.net/cskardon/archive/2008/06/23/dispose-of-a-wpf-usercontrol-ish.aspx
它提到了订阅Dispatcher_ShutDownStarted来处理你的资源。
Dispatcher.ShutdownStarted
事件仅在应用程序结束时触发。 只有当控制失效时才能调用处理逻辑。 特别是在应用程序运行时多次使用控件时,它释放资源。 所以ioWint的解决scheme是可取的。 代码如下:
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 }; }
你必须小心使用析构函数。 这将在GC终结器线程上调用。 在某些情况下,你释放的资源可能不喜欢在与创build它不同的线程上释放。
我使用以下交互行为向WPF UserControls提供卸载事件。 您可以将行为包含在UserControls XAML中。 所以你可以拥有这个function,而不用把它放在每一个UserControl中。
XAML声明:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" <i:Interaction.Behaviors> <behaviors:UserControlSupportsUnloadingEventBehavior UserControlClosing="UserControlClosingHandler" /> </i:Interaction.Behaviors>
CodeBehind处理程序:
private void UserControlClosingHandler(object sender, EventArgs e) { // to unloading stuff here }
行为代码:
/// <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); } }
我的情况是有点不同,但意图是相同的,我想知道什么时候宿主我的用户控制的父窗口closures/closures视图(即我的用户控件)应该调用演示者oncloseView执行一些function,并执行清理。 (好吧,我们正在WPF PRISM应用程序上实现MVP模式)。
我只是觉得在UserControl的Loaded事件中,我可以将ParentWindowClosing方法连接到父窗口closures事件。 这样,我的用户控件可以知道什么时候父窗口被closures,并采取相应的行动!
UserControl有一个析构函数,为什么不使用它?
~MyWpfControl() { // Dispose of any Disposable items here }