타사에서 사용할 사용자 지정 WPF 사용자 정의 컨트롤을 만들었습니다. 내 컨트롤에는 일회용 인 개인 멤버가 있으며 포함하는 창 / 응용 프로그램이 닫히면 dispose 메서드가 항상 호출되도록하고 싶습니다. 그러나 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;
}
}
}
지금까지 찾은 유일한 해결책은 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 의 솔루션이 바람직합니다. 코드는 다음과 같습니다.
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 Finalizer 스레드에서 호출됩니다. 경우에 따라 해제 된 리소스가 생성 된 스레드와 다른 스레드에서 해제되는 것을 좋아하지 않을 수 있습니다.
답변
다음 상호 작용 동작을 사용하여 WPF UserControls에 언로드 이벤트를 제공합니다. UserControls XAML에 동작을 포함 할 수 있습니다. 따라서 모든 단일 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);
}
}
답변
내 시나리오는 약간 다르지만 의도는 동일합니다. 내 사용자 컨트롤을 호스팅하는 부모 창이 닫히거나 닫히는시기를 알고 싶습니다.보기 (예 : 내 usercontrol)는 일부 기능을 실행하고 정리를 수행하기 위해 closeView에서 발표자를 호출해야합니다. (우리는 WPF PRISM 애플리케이션에서 MVP 패턴을 구현하고 있습니다).
방금 usercontrol의 Loaded 이벤트에서 ParentWindowClosing 메서드를 Parent windows Closing 이벤트에 연결할 수 있다고 생각했습니다. 이렇게하면 내 Usercontrol이 부모 창이 닫힐 때를 인식하고 그에 따라 행동 할 수 있습니다!
답변
언로드는 모두라고 생각하지만 4.7에는 하드가 존재합니다. 그러나 이전 버전의 .Net을 가지고 노는 경우로드 방법에서 다음을 수행하십시오.
e.Handled = true;
로드가 처리 될 때까지 이전 버전이 언로드되지 않을 것이라고 생각합니다. 다른 사람들이 여전히이 질문을하고 있고 이것이 해결책으로 제안 된 것을 보지 못했기 때문에 게시했습니다. 나는 .Net을 일년에 몇 번만 만졌고 몇 년 전에 이것을 만났습니다. 하지만로드가 끝날 때까지 언로드가 호출되지 않는 것만 큼 간단한 지 궁금합니다. 그것이 나를 위해 작동하는 것처럼 보이지만, 다시 새로운 .Net에서는 로딩이 처리됨으로 표시되지 않더라도 항상 언로드를 호출하는 것 같습니다.
답변
UserControl에는 소멸자가 있습니다. 왜 그것을 사용하지 않습니까?
~MyWpfControl()
{
// Dispose of any Disposable items here
}