Search code examples
c#wpfremote-desktop

How to prevent calling loaded unloaded methods of Pages and UCs when user reconnects RDC in WPF C#?


In my WPF app i have so many UCs and controls i want to prevent them loading and unloading after user reconnects rdc I've done alot of research to solve the issue but nothing is working.

When reconnecting to a remote desktop session this happpens.

  • Controls being unloaded then reloaded

  • Controls within DataTemplates being completed re-created is there a way to prevent loading and unloading of controls

my app is running on .NET framework version 4.6
here is my code

public uc()
{
    uc.Loaded +=somemethod;
}
somemethod(){
TextBox tb = new TextBox();
this.AddChild(tb); // after getting called again it adds another textbox 
}

after reconnect the first breakpoint that gets hit is in the constructor and I don't know how to debug it further because the stack trace only shows [external code] before this.


Solution

  • As per @GerrySchmitz's comment, I used a flag to track whether the control is loaded or not, setting it accordingly. However, in my app, some user controls (UCs) have the main window as their direct parent, while others have a page or a frame as their parent. After a lot of thinking and trying different solutions, I finally created a method that effectively prevents the problem. While this isn't a direct solution, it's a trick that helps avoid the issue. Here's the code for it

    In mainwindow.xaml.cs

    private bool IsDisconnect = false; // flag to check whether session is disconnected or not.
    private int counter;// to check the number of controls that are getting loaded or unloaded 
    
    public MainWindow()
    {
        SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
        EventManager.RegisterClassHandler(typeof(UserControl), UserControl.LoadedEvent, new RoutedEventHandler(UserControlLoaderUnloaderHandler));
        EventManager.RegisterClassHandler(typeof(UserControl), UserControl.UnloadedEvent, new RoutedEventHandler(UserControlLoaderUnloaderHandler));
        EventManager.RegisterClassHandler(typeof(Page), Page.LoadedEvent, new RoutedEventHandler(PageLoaderUnLoaderHandler));
        EventManager.RegisterClassHandler(typeof(Page), Page.UnloadedEvent, new RoutedEventHandler(PageLoaderUnLoaderHandler));
         //rest of the code
    }
    
    private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
            {
                if (e.Reason == SessionSwitchReason.) IsDisconnect = true;
            }
    
    private void UserControlLoaderUnloaderHandler(object sender, RoutedEventArgs e)
            {
                var userControl = sender as UserControl;
                if (userControl != null && IsDisconnect)
                {
                    e.Handled = true;
                    if (e.RoutedEvent == FrameworkElement.UnloadedEvent) counter++;
                    if (e.RoutedEvent == FrameworkElement.LoadedEvent) counter--;
                }
                if (IsDisconnect && counter == 0) IsDisconnect = false;
            }
    
            private void PageLoaderUnLoaderHandler(object sender, RoutedEventArgs e)
            {
                var page = sender as Page;
                if (page != null && IsDisconnect)
                {
                    e.Handled = true;
                    if (e.RoutedEvent == FrameworkElement.UnloadedEvent) counter++;
                    if (e.RoutedEvent == FrameworkElement.LoadedEvent) counter--;
                }
                if (IsDisconnect && counter == 0) IsDisconnect = false;
            }
    

    When RemoteDisconnect is the session switch cause, the SystemEvents_SessionSwitch method sets the IsDisconnect flag to true.

    and in the UserControlLoaderUnloaderHandler and PageLoaderUnLoaderHandler methods, whenever a user control (UC) or page is unloaded, the same number of them will eventually need to be loaded again after a remote disconnect. To prevent the Loaded method in the UCs or Pages from being called, we set e.Handled = true;

    By increasing a counter when UCs and pages are unloaded and decreasing it when they are loaded, we are able to keep track of how many UCs and pages are being loaded and unloaded. We use the condition (IsDisconnect && counter==0) to set the IsDisconnect flag to false after all of the UCs and pages have been loaded back, or when the counter hits zero.

    So far, this solution has been effective. You can modify it by changing the controls and making necessary adjustments accordingly.