programing

WPF 사용자 컨트롤 배치

i4 2023. 5. 1. 19:56
반응형

WPF 사용자 컨트롤 배치

타사에서 사용할 사용자 지정 WPF 사용자 컨트롤을 만들었습니다.내 컨트롤에는 처분 가능한 개인 멤버가 있으며, 포함된 창/애플리케이션이 닫히면 항상 처분 방법이 호출되도록 하고 싶습니다.그러나 사용자 컨트롤은 일회용이 아닙니다.

ID 일회용 인터페이스를 구현하고 Unloaded 이벤트에 가입하려고 했지만 호스트 응용 프로그램이 닫힐 때 호출되지 않습니다.MSDN에서 Unloaded 이벤트가 전혀 발생하지 않을 수 있다고 합니다.또한 사용자가 테마를 변경할 때 두 번 이상 트리거될 수도 있습니다.

가능하다면 특정 폐기 방법을 호출하는 것을 기억하는 내 통제력의 소비자에게 의존하고 싶지 않습니다.

 public partial class MyWpfControl : UserControl
 {
     SomeDisposableObject x;

     // where does this code go?
     void Somewhere() 
     {
         if (x != null)
         {
             x.Dispose();
             x = null;
         }

     }
 }

지금까지 찾은 유일한 해결책은 Dispatcher의 Shutdown Started 이벤트에 가입하는 것입니다.이것이 합리적인 접근입니까?

this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;

여기서 흥미로운 블로그 게시물: WPF 사용자 컨트롤 폐기(ish)

여기에는 디스패치에 가입하는 것이 언급되어 있습니다.종료 - 리소스를 폐기하기 시작했습니다.

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에 언로드 이벤트를 제공하기 위해 다음과 같은 Interactivity Behavior를 사용합니다.UserControls XAML에 동작을 포함할 수 있습니다. 따라서 모든 UserControl에 논리를 배치하지 않고도 기능을 사용할 수 있습니다.

XAML 선언:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<i:Interaction.Behaviors>
    <behaviors:UserControlSupportsUnloadingEventBehavior UserControlClosing="UserControlClosingHandler" />
</i:Interaction.Behaviors>

코드백 핸들러:

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);
    }
}

제 시나리오는 조금 다르지만, 제 사용자 컨트롤을 호스팅하는 상위 창이 닫히거나 닫힐 때를 알고 싶습니다. 뷰(즉, 제 사용자 컨트롤)가 클로즈 뷰의 발표자를 호출하여 일부 기능을 실행하고 정리를 수행해야 합니다. (WPF PRISM 애플리케이션에서 MVP 패턴을 구현하고 있습니다.)

방금 사용자 컨트롤의 Loaded 이벤트에서 ParentWindowClosing 메서드를 ParentwindowClosing 이벤트에 연결할 수 있습니다.이렇게 하면 상위 창이 닫힐 때 사용자 컨트롤이 이를 인식하고 이에 따라 작업할 수 있습니다!

언로드는 모두라고 하지만 4.7에는 거의 존재하지 않습니다.그러나 이전 버전의 를 사용하는 경우에는Net, 로딩 방법으로 다음을 수행합니다.

e.Handled = true;

이전 버전은 로딩이 처리될 때까지 언로드하지 않을 것 같습니다.다른 사람들이 여전히 이 질문을 하는 것을 보기 때문에 게시하는 것이고, 이 질문이 해결책으로 제안된 것을 보지 못했습니다.만지기만 합니다.일년에 몇 번씩 인터넷을 하다가 몇 년 전에 이런 일을 당했습니다.하지만, 저는 로딩이 끝날 때까지 언로드가 호출되지 않는 것처럼 간단한 것인지 궁금합니다.저한테는 효과가 있는 것 같지만, 다시 새로운 것으로.Net 로딩이 처리된 것으로 표시되지 않더라도 항상 언로드를 호출하는 것 같습니다.

사용자 컨트롤에는 소멸자가 있습니다. 사용하는 것이 어떻습니까?

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

언급URL : https://stackoverflow.com/questions/502761/disposing-wpf-user-controls

반응형