ContentPage.xaml.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using CommunityToolkit.Mvvm.Messaging; 6 using Microsoft.CmdPal.Core.ViewModels; 7 using Microsoft.CmdPal.Core.ViewModels.Messages; 8 using Microsoft.UI.Dispatching; 9 using Microsoft.UI.Xaml; 10 using Microsoft.UI.Xaml.Controls; 11 using Microsoft.UI.Xaml.Navigation; 12 13 namespace Microsoft.CmdPal.UI; 14 15 /// <summary> 16 /// An empty page that can be used on its own or navigated to within a Frame. 17 /// </summary> 18 public sealed partial class ContentPage : Page, 19 IRecipient<ActivateSelectedListItemMessage>, 20 IRecipient<ActivateSecondaryCommandMessage> 21 { 22 private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread(); 23 24 public ContentPageViewModel? ViewModel 25 { 26 get => (ContentPageViewModel?)GetValue(ViewModelProperty); 27 set => SetValue(ViewModelProperty, value); 28 } 29 30 // Using a DependencyProperty as the backing store for ViewModel. This enables animation, styling, binding, etc... 31 public static readonly DependencyProperty ViewModelProperty = 32 DependencyProperty.Register(nameof(ViewModel), typeof(ContentPageViewModel), typeof(ContentPage), new PropertyMetadata(null)); 33 34 public ContentPage() 35 { 36 this.InitializeComponent(); 37 this.Unloaded += OnUnloaded; 38 } 39 40 private void OnUnloaded(object sender, RoutedEventArgs e) 41 { 42 // Unhook from everything to ensure nothing can reach us 43 // between this point and our complete and utter destruction. 44 WeakReferenceMessenger.Default.UnregisterAll(this); 45 } 46 47 protected override void OnNavigatedTo(NavigationEventArgs e) 48 { 49 if (e.Parameter is not AsyncNavigationRequest navigationRequest) 50 { 51 throw new InvalidOperationException($"Invalid navigation parameter: {nameof(e.Parameter)} must be {nameof(AsyncNavigationRequest)}"); 52 } 53 54 if (navigationRequest.TargetViewModel is not ContentPageViewModel contentPageViewModel) 55 { 56 throw new InvalidOperationException($"Invalid navigation target: AsyncNavigationRequest.{nameof(AsyncNavigationRequest.TargetViewModel)} must be {nameof(ContentPageViewModel)}"); 57 } 58 59 ViewModel = contentPageViewModel; 60 61 if (!WeakReferenceMessenger.Default.IsRegistered<ActivateSelectedListItemMessage>(this)) 62 { 63 WeakReferenceMessenger.Default.Register<ActivateSelectedListItemMessage>(this); 64 } 65 66 if (!WeakReferenceMessenger.Default.IsRegistered<ActivateSecondaryCommandMessage>(this)) 67 { 68 WeakReferenceMessenger.Default.Register<ActivateSecondaryCommandMessage>(this); 69 } 70 71 base.OnNavigatedTo(e); 72 } 73 74 protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) 75 { 76 base.OnNavigatingFrom(e); 77 WeakReferenceMessenger.Default.Unregister<ActivateSelectedListItemMessage>(this); 78 WeakReferenceMessenger.Default.Unregister<ActivateSecondaryCommandMessage>(this); 79 80 // Clean-up event listeners 81 if (e.NavigationMode != NavigationMode.New) 82 { 83 ViewModel?.SafeCleanup(); 84 CleanupHelper.Cleanup(this); 85 } 86 87 ViewModel = null; 88 } 89 90 // this comes in on Enter keypresses in the SearchBox 91 public void Receive(ActivateSelectedListItemMessage message) 92 { 93 ViewModel?.InvokePrimaryCommandCommand?.Execute(ViewModel); 94 } 95 96 // this comes in on Ctrl+Enter keypresses in the SearchBox 97 public void Receive(ActivateSecondaryCommandMessage message) 98 { 99 ViewModel?.InvokeSecondaryCommandCommand?.Execute(ViewModel); 100 } 101 }