diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/MainWindowViewModel.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/MainWindowViewModel.cs
index f73b39c..d1766a5 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/MainWindowViewModel.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/MainWindowViewModel.cs
@@ -10,7 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
///
/// Main window ViewModel coordinating all panels.
///
-public partial class MainWindowViewModel : ObservableObject
+public partial class MainWindowViewModel : ObservableObject, IDisposable
{
private readonly IUiDispatcher _dispatcher;
private readonly IOpcUaClientServiceFactory _factory;
@@ -411,6 +411,21 @@ public partial class MainWindowViewModel : ObservableObject
});
}
+ ///
+ /// Detaches the connection-state handler and disposes the OPC UA client service, releasing
+ /// the session, certificate validator, and any background reconnect resources.
+ ///
+ public void Dispose()
+ {
+ if (_service != null)
+ {
+ _service.ConnectionStateChanged -= OnConnectionStateChanged;
+ Subscriptions?.Teardown();
+ Alarms?.Teardown();
+ _service.Dispose();
+ }
+ }
+
private static string[]? ParseFailoverUrls(string? csv)
{
if (string.IsNullOrWhiteSpace(csv))
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Views/MainWindow.axaml.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Views/MainWindow.axaml.cs
index 108f908..7178ab5 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Views/MainWindow.axaml.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Views/MainWindow.axaml.cs
@@ -140,7 +140,10 @@ public partial class MainWindow : Window
protected override void OnClosing(WindowClosingEventArgs e)
{
if (DataContext is MainWindowViewModel vm)
+ {
vm.SaveSettings();
+ vm.Dispose();
+ }
base.OnClosing(e);
}
}