using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using Heisig.HMI.AdsManager; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System.Windows; using System.Windows.Controls; using TcEventLoggerAdsProxyLib; namespace UniperHMI; public sealed partial class MainWindowVM : ObservableObject, IRecipient, IDisposable { [ObservableProperty] private StringControlButtonVM dummyStringVM; [ObservableProperty] private Page currentPage; [ObservableProperty] private bool canNavigateBack; [ObservableProperty] private Visibility statusBarVisible; [ObservableProperty] private string breadcrumb; private readonly IAdsManager _adsManager; private readonly IConfiguration _config; private readonly TcEventLogger _eventlogger; // Last active event [ObservableProperty] private string currentActiveEvent = ""; private readonly object _lock = new(); // Empty page private readonly Page _emptyPage; // Last navigate message private readonly Stack _messageStack = new(); NavigateMessage? _currentMessage; // Events page view model [ObservableProperty] EventsPageVM _eventsPageVM; // Settings page viem model SettingsPageVM? _settingsPageVM; // Hot Coolplate page view model HotCoolPlatePageVM? _hotCoolplatePageVM; // Chuck Magazin page view model ChuckMagazinPageVM? _chuckMagazinPageVM; // Kuka Robot page view model KukaRobotPageVM? _kukaRobotPageVM; public MainWindowVM(IAdsManager adsManager, IConfiguration config, TcEventLogger eventLogger) { _adsManager = adsManager; _config = config; // Create dummy string DummyStringVM = new StringControlButtonVM(); // Create empty page _emptyPage = new(); // Create events page viewmodel _eventlogger = eventLogger; _eventsPageVM = new(_eventlogger); CurrentPage = _emptyPage; _currentMessage = new NavigateMessage("", typeof(Page)); _messageStack.Push(_currentMessage); WeakReferenceMessenger.Default.Register(this); breadcrumb = ""; } [RelayCommand] private void SettingsWindow() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); NavigateMessage message = new("", typeof(SettingsPage)); Receive(message); } [RelayCommand] public void AutomaticModeClicked() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new(_config["AutomaticModeVarName"]!, typeof(AutomaticModePage)); Receive(message); } [RelayCommand] public void ManualModeClicked() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new("", typeof(BatteryOverviewPage)); Receive(message); } [RelayCommand] public void EventsListClicked() { StatusBarVisible = Visibility.Collapsed; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new("", typeof(EventsPage)); Receive(message); } [RelayCommand] public void KukaRobotClicked() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new(_config["KukaRobotVarName"]!, typeof(KukaRobotPage)); Receive(message); } [RelayCommand] public void HotCoolplateClicked() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new(_config["HotCoolplateVarName"]!, typeof(HotCoolPlatePage)); Receive(message); } [RelayCommand] public void ChuckMagazinClicked() { StatusBarVisible = Visibility.Visible; _messageStack.Clear(); _currentMessage = new NavigateMessage("", typeof(Page)); NavigateMessage message = new(_config["ChuckMagazinVarName"]!, typeof(ChuckMagazinPage)); Receive(message); } [RelayCommand] public void NavigateBack() { if (_messageStack.Count == 0) { CanNavigateBack = false; return; } _currentMessage = _messageStack.Pop(); // Update if we can use the navigate back button if (_messageStack.Count > 0) CanNavigateBack = true; else { StatusBarVisible = Visibility.Visible; CanNavigateBack = false; } // Remove last two entrys from Breadcrumbs int index = -1; for (int i = 0; i < 2; i++) { index = Breadcrumb.LastIndexOf('>'); if (index != -1) Breadcrumb = Breadcrumb[..index]; } // Navigate to page Navigate(_currentMessage); } // Only use for forward traversal! public void Receive(NavigateMessage message) { // Only change page if its a new page type if (CurrentPage.GetType() == message.type) return; // Push current message if (_currentMessage != null) _messageStack.Push(_currentMessage); // Save current message for later push _currentMessage = message; // Set can navigate back CanNavigateBack = true; Navigate(message); } private void Navigate(NavigateMessage message) { // Dispose current pages viewmodel if (CurrentPage.DataContext is IDisposable viewModel) { CurrentPage.DataContext = null; viewModel.Dispose(); } // Create new page switch (message.type.Name) { case nameof(AutomaticModePage): var automaticModeViewModel = (AutomaticModePageVM)ActivatorUtilities.CreateInstance(App.AppHost!.Services, typeof(AutomaticModePageVM), message.VariableName); //App.AppHost!.Services.GetRequiredService(); AutomaticModePage automaticModePage = new() { DataContext = automaticModeViewModel }; CurrentPage = automaticModePage; Breadcrumb = "> Automatic"; break; case nameof(BatteryOverviewPage): var batteryOverviewPageVM = App.AppHost!.Services.GetRequiredService(); BatteryOverviewPage batteryOverviewPage = new() { DataContext = batteryOverviewPageVM }; CurrentPage = batteryOverviewPage; Breadcrumb = "> Manual"; break; case nameof(StringOverviewPage): var stringOverviewVM = (StringOverviewPageVM)ActivatorUtilities.CreateInstance(App.AppHost!.Services, typeof(StringOverviewPageVM), message.VariableName); StringOverviewPage stringPage = new() { DataContext = stringOverviewVM }; CurrentPage = stringPage; if (message.Header.Length > 0) AppendBreadcrumb(message.Header); break; case nameof(ModuleOverviewPage): var moduleOverviewVM = (ModuleOverviewPageVM)ActivatorUtilities.CreateInstance(App.AppHost!.Services, typeof(ModuleOverviewPageVM), message.VariableName); ModuleOverviewPage modulePage = new() { DataContext = moduleOverviewVM }; CurrentPage = modulePage; if (message.Header.Length > 0) AppendBreadcrumb(message.Header); break; case nameof(UnitOverviewPage): var unitOverviewVM = (UnitOverviewPageVM)ActivatorUtilities.CreateInstance(App.AppHost!.Services, typeof(UnitOverviewPageVM), message.VariableName); unitOverviewVM.UnitName = message.Header; UnitOverviewPage unitPage = new() { DataContext = unitOverviewVM }; CurrentPage = unitPage; if (message.Header.Length > 0) AppendBreadcrumb(message.Header); break; case nameof(EventsPage): #pragma warning disable MVVMTK0034 // Direct field reference to [ObservableProperty] backing field EventsPage eventsPage = new() { DataContext = _eventsPageVM }; #pragma warning restore MVVMTK0034 // Direct field reference to [ObservableProperty] backing field CurrentPage = eventsPage; Breadcrumb = " > Events"; break; case nameof(SettingsPage): // Create seetings page view model only once if (_settingsPageVM == null) _settingsPageVM = new(_adsManager, "GVL_CONFIG.stUnitConfig"); SettingsPage settingsPage = new() { DataContext = _settingsPageVM }; CurrentPage = settingsPage; Breadcrumb = " > Settings"; break; case nameof(KukaRobotPage): // Create page view model only once if (_kukaRobotPageVM == null) _kukaRobotPageVM = new(_adsManager, "GVL_CONFIG.stRobotConfig"); KukaRobotPage kukaRobotPage = new() { DataContext = _kukaRobotPageVM }; CurrentPage = kukaRobotPage; Breadcrumb = " > Kuka Roboter"; break; case nameof(HotCoolPlatePage): if (_hotCoolplatePageVM == null) _hotCoolplatePageVM = new(_adsManager, "GVL_Config.stHotCoolplateConfig"); HotCoolPlatePage hotCoolPlatePage = new() {DataContext = _hotCoolplatePageVM }; CurrentPage = hotCoolPlatePage; Breadcrumb = " > Heiz- /Kühlplatte"; break; case nameof(ChuckMagazinPage): if (_chuckMagazinPageVM == null) _chuckMagazinPageVM = new(_adsManager, "GVL_Config.stChuckMagazinConfig"); ChuckMagazinPage chuckMagazinPage = new() { DataContext= _chuckMagazinPageVM }; CurrentPage = chuckMagazinPage; Breadcrumb = " > Tellermagazin"; break; default: CurrentPage = new Page(); break; } } private void AppendBreadcrumb(string path) { if (Breadcrumb[^1] != ' ') Breadcrumb += " > " + path; else Breadcrumb += "> " + path; } [RelayCommand] private void AckAlarms() { _adsManager.WriteValue("GVL_SCADA.stAckAlarmsButton.xRequest", true); } public void Dispose() { // Dispose current pages viewmodel if (CurrentPage.DataContext is IDisposable viewModel) { CurrentPage.DataContext = null; viewModel.Dispose(); } DummyStringVM.Dispose(); } }