Удаление пользовательских элементов управления WPF
Я создал пользовательский пользовательский элемент управления WPF, который предназначен для использования третьей стороной. У моего элемента управления есть закрытый член, который является одноразовым, и я хотел бы убедиться, что его метод dispose всегда будет вызван после закрытия windows / приложения. Однако UserControl недоступен. Я попытался реализовать интерфейс IDisposable и подписаться на событие Unloaded, но не вызывается, когда приложение-хост закрывается. Если это вообще возможно, я не хочу полагаться на потребителей моего контроля, помня, чтобы вызвать конкретный метод Dispose.
public partial class MyWpfControl : UserControl { SomeDisposableObject x; // where does this code go? void Somewhere() { if (x != null) { x.Dispose(); x = null; } } }
Единственное решение, которое я нашел до сих пор, – это подписаться на событие ShutdownStarted Dispatcher. Это разумный подход?
this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
- «Коллекция Controls не может быть изменена, поскольку элемент управления содержит блоки кода"
- Как визуализировать формулу в WPF или WinForms
- Как включить поддержку дизайна в пользовательском элементе управления?
- Анимация WPF: привязка к атрибуту «To» анимации раскадровки
- Как WPF UserControl наследует WPC UserControl?
- Как получить полный URL-адрес страницы, на которой я нахожусь в C #
- Как добавить событие в UserControl в C #?
- Наследование с помощью UserControl в WPF
- В чем разница между библиотекой пользовательского контроля и библиотекой пользовательского контроля?
- Конструктор UserControl с параметрами в C #
- Текстовое свойство в UserControl в C #
Интересный блог здесь:
http://geekswithblogs.net/cskardon/archive/2008/06/23/dispose-of-a-wpf-usercontrol-ish.aspx
Он упоминает подписку на Dispatcher_ShutDownStarted, чтобы избавиться от ваших ресурсов.
Событие Dispatcher.ShutdownStarted
запускается только в конце приложения. Стоит назвать логику утилизации только тогда, когда управление выходит из употребления. В частности, он освобождает ресурсы, когда управление используется многократно во время выполнения приложения. Поэтому решение ioWint предпочтительнее. Вот код:
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 }; }
Вы должны быть осторожны, используя деструктор. Это будет вызвано в streamе Finalizer GC. В некоторых случаях ресурсы, которые ваше освобождение может не нравиться, выпускаются в другом streamе с того, на котором они были созданы.
Я использую следующее Interactivity Behavior, чтобы обеспечить событие разгрузки для WPF UserControls. Вы можете включить поведение в UserControls XAML. Таким образом, вы можете иметь функциональность, не помещая логику в каждый отдельный UserControl.
Объявление XAML:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Обработчик CodeBehind:
private void UserControlClosingHandler(object sender, EventArgs e) { // to unloading stuff here }
Код поведения:
/// /// This behavior raises an event when the containing window of a is closing. /// public class UserControlSupportsUnloadingEventBehavior : System.Windows.Interactivity.Behavior { 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; } /// /// Registers to the containing windows Closing event when the UserControl is loaded. /// 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; } /// /// The containing window is closing, raise the UserControlClosing event. /// private void WindowClosingHandler(object sender, CancelEventArgs e) { OnUserControlClosing(); } /// /// This event will be raised when the containing window of the associated is closing. /// public event EventHandler UserControlClosing; protected virtual void OnUserControlClosing() { var handler = UserControlClosing; if (handler != null) handler(this, EventArgs.Empty); } }
Мой сценарий немного отличается, но намерение – это то же самое, что я хотел бы знать, когда родительское окно, в котором находится мой пользовательский элемент управления, закрывается / закрывается, поскольку представление (то есть мое пользовательское управление) должно вызывать презентаторов oncloseView для выполнения некоторых функций и выполнения очистки. (хорошо мы реализуем шаблон MVP в приложении WPF PRISM).
Я просто понял, что в событии Loaded пользовательского контроля я могу подключить метод ParentWindowClosing к событию закрытия родительского windows. Таким образом, мой Usercontrol может знать, когда окно родителя закрывается и действует соответствующим образом!
Я думаю, что разгрузка называется все, но в сущности существует в 4.7. Но если вы играете со старыми версиями .Net, попробуйте сделать это в своем методе загрузки:
e.Handled = true;
Я не думаю, что старые версии будут разгружаться до загрузки. Просто публиковать, потому что я вижу, что другие все еще задают этот вопрос и не видели, что это предлагается как решение. Я только несколько раз касаюсь .Net несколько раз в год, и несколько лет назад столкнулся с этим. Но, интересно, это так же просто, как разгрузка не вызывается до завершения загрузки. Похоже, что это работает для меня, но снова в более новой .Net, похоже, всегда вызывается разгрузка, даже если загрузка не отмечена как обработанная.
У UserControl есть Destructor, почему бы вам не использовать это?
~MyWpfControl() { // Dispose of any Disposable items here }