diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs index a3b008206d6..16252086e2b 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs @@ -9,20 +9,19 @@ namespace Flow.Launcher.Resources.Pages { public partial class WelcomePage1 { - public Settings Settings { get; private set; } - private WelcomeViewModel _viewModel; + public Settings Settings { get; } = Ioc.Default.GetRequiredService(); + private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + _viewModel.PageNum = 1; + if (!IsInitialized) { - Settings = Ioc.Default.GetRequiredService(); - _viewModel = Ioc.Default.GetRequiredService(); InitializeComponent(); } - // Sometimes the navigation is not triggered by button click, - // so we need to reset the page number - _viewModel.PageNum = 1; base.OnNavigatedTo(e); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs index a63edbcda7c..37767f1285f 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs @@ -11,20 +11,19 @@ namespace Flow.Launcher.Resources.Pages { public partial class WelcomePage2 { - public Settings Settings { get; private set; } - private WelcomeViewModel _viewModel; + public Settings Settings { get; } = Ioc.Default.GetRequiredService(); + private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + _viewModel.PageNum = 2; + if (!IsInitialized) { - Settings = Ioc.Default.GetRequiredService(); - _viewModel = Ioc.Default.GetRequiredService(); InitializeComponent(); } - // Sometimes the navigation is not triggered by button click, - // so we need to reset the page number - _viewModel.PageNum = 2; base.OnNavigatedTo(e); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs index 4a6610e6173..4c3184f8c57 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs @@ -7,20 +7,19 @@ namespace Flow.Launcher.Resources.Pages { public partial class WelcomePage3 { - public Settings Settings { get; private set; } - private WelcomeViewModel _viewModel; + public Settings Settings { get; } = Ioc.Default.GetRequiredService(); + private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + _viewModel.PageNum = 3; + if (!IsInitialized) { - Settings = Ioc.Default.GetRequiredService(); - _viewModel = Ioc.Default.GetRequiredService(); InitializeComponent(); } - // Sometimes the navigation is not triggered by button click, - // so we need to reset the page number - _viewModel.PageNum = 3; base.OnNavigatedTo(e); } } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs index 1ee3284d22e..63c9b9a7afa 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs @@ -7,20 +7,19 @@ namespace Flow.Launcher.Resources.Pages { public partial class WelcomePage4 { - public Settings Settings { get; private set; } - private WelcomeViewModel _viewModel; + public Settings Settings { get; } = Ioc.Default.GetRequiredService(); + private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + _viewModel.PageNum = 4; + if (!IsInitialized) { - Settings = Ioc.Default.GetRequiredService(); - _viewModel = Ioc.Default.GetRequiredService(); InitializeComponent(); } - // Sometimes the navigation is not triggered by button click, - // so we need to reset the page number - _viewModel.PageNum = 4; base.OnNavigatedTo(e); } } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs index 6328c991449..8db0a9f7e08 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs @@ -10,20 +10,19 @@ namespace Flow.Launcher.Resources.Pages { public partial class WelcomePage5 { - public Settings Settings { get; private set; } - private WelcomeViewModel _viewModel; + public Settings Settings { get; } = Ioc.Default.GetRequiredService(); + private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + _viewModel.PageNum = 5; + if (!IsInitialized) { - Settings = Ioc.Default.GetRequiredService(); - _viewModel = Ioc.Default.GetRequiredService(); InitializeComponent(); } - // Sometimes the navigation is not triggered by button click, - // so we need to reset the page number - _viewModel.PageNum = 5; base.OnNavigatedTo(e); } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs index e57cba6d409..47532b243eb 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs @@ -1,19 +1,29 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPaneAbout { private SettingsPaneAboutViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPaneAbout); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } base.OnNavigatedTo(e); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs index 31653962dfd..753cb7b0e3b 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs @@ -1,19 +1,29 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPaneGeneral { private SettingsPaneGeneralViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPaneGeneral); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } base.OnNavigatedTo(e); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs index 8b757bd60a5..202869bc5d0 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs @@ -1,19 +1,29 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPaneHotkey { private SettingsPaneHotkeyViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPaneHotkey); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } base.OnNavigatedTo(e); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs index 5ddfe465009..c0a77957ac8 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs @@ -11,13 +11,22 @@ namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPanePluginStore { private SettingsPanePluginStoreViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPanePluginStore); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } _viewModel.PropertyChanged += ViewModel_PropertyChanged; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs index e9490804ab5..f486a3443ce 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs @@ -11,13 +11,22 @@ namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPanePlugins { private SettingsPanePluginsViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPanePlugins); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } _viewModel.PropertyChanged += ViewModel_PropertyChanged; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs index 258f2a4adbf..3e617229d4f 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs @@ -1,19 +1,29 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPaneProxy { private SettingsPaneProxyViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPaneProxy); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } base.OnNavigatedTo(e); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs index cee8e4ae468..170003994ed 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs @@ -1,19 +1,29 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.Views; public partial class SettingsPaneTheme { private SettingsPaneThemeViewModel _viewModel = null!; + private readonly SettingWindowViewModel _settingViewModel = Ioc.Default.GetRequiredService(); protected override void OnNavigatedTo(NavigationEventArgs e) { - if (!IsInitialized) + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page type + _settingViewModel.PageType = typeof(SettingsPaneTheme); + + // If the navigation is not triggered by button click, view model will be null again + if (_viewModel == null) { _viewModel = Ioc.Default.GetRequiredService(); DataContext = _viewModel; + } + if (!IsInitialized) + { InitializeComponent(); } base.OnNavigatedTo(e); diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index cf84317acb0..ebbb3841482 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; @@ -18,6 +19,7 @@ public partial class SettingWindow #region Private Fields private readonly Settings _settings; + private readonly SettingWindowViewModel _viewModel; #endregion @@ -26,8 +28,8 @@ public partial class SettingWindow public SettingWindow() { _settings = Ioc.Default.GetRequiredService(); - var viewModel = Ioc.Default.GetRequiredService(); - DataContext = viewModel; + _viewModel = Ioc.Default.GetRequiredService(); + DataContext = _viewModel; InitializeComponent(); UpdatePositionAndState(); @@ -48,10 +50,37 @@ private void OnLoaded(object sender, RoutedEventArgs e) hwndTarget.RenderMode = RenderMode.SoftwareOnly; // Must use software only render mode here UpdatePositionAndState(); + + _viewModel.PropertyChanged += ViewModel_PropertyChanged; + } + + // Sometimes the navigation is not triggered by button click, + // so we need to update the selected item here + private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(SettingWindowViewModel.PageType): + var selectedIndex = _viewModel.PageType.Name switch + { + nameof(SettingsPaneGeneral) => 0, + nameof(SettingsPanePlugins) => 1, + nameof(SettingsPanePluginStore) => 2, + nameof(SettingsPaneTheme) => 3, + nameof(SettingsPaneHotkey) => 4, + nameof(SettingsPaneProxy) => 5, + nameof(SettingsPaneAbout) => 6, + _ => 0 + }; + NavView.SelectedItem = NavView.MenuItems[selectedIndex]; + break; + } } private void OnClosed(object sender, EventArgs e) { + _viewModel.PropertyChanged -= ViewModel_PropertyChanged; + // If app is exiting, settings save is not needed because main window closing event will handle this if (App.Exiting) return; // Save settings when window is closed @@ -212,6 +241,7 @@ private void NavigationView_SelectionChanged(NavigationView sender, NavigationVi { if (args.IsSettingsSelected) { + _viewModel.SetPageType(typeof(SettingsPaneGeneral)); ContentFrame.Navigate(typeof(SettingsPaneGeneral)); } else @@ -234,7 +264,11 @@ private void NavigationView_SelectionChanged(NavigationView sender, NavigationVi nameof(About) => typeof(SettingsPaneAbout), _ => typeof(SettingsPaneGeneral) }; - ContentFrame.Navigate(pageType); + // Only navigate if the page type changes to fix navigation forward/back issue + if (_viewModel.SetPageType(pageType)) + { + ContentFrame.Navigate(pageType); + } } } @@ -252,7 +286,8 @@ private void NavView_Loaded(object sender, RoutedEventArgs e) private void ContentFrame_Loaded(object sender, RoutedEventArgs e) { - NavView.SelectedItem ??= NavView.MenuItems[0]; /* Set First Page */ + _viewModel.SetPageType(null); // Set page type to null so that NavigationView_SelectionChanged can navigate the frame + NavView.SelectedItem = NavView.MenuItems[0]; /* Set First Page */ } #endregion diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 17a1a2b50f1..1134a81b896 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Infrastructure.UserSettings; +using System; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; namespace Flow.Launcher.ViewModel; @@ -12,6 +13,28 @@ public SettingWindowViewModel(Settings settings) _settings = settings; } + public bool SetPageType(Type pageType) + { + if (_pageType == pageType) return false; + + _pageType = pageType; + return true; + } + + private Type _pageType = null; + public Type PageType + { + get => _pageType; + set + { + if (_pageType != value) + { + _pageType = value; + OnPropertyChanged(); + } + } + } + public double SettingWindowWidth { get => _settings.SettingWindowWidth;