1+ using CommunityToolkit . Mvvm . Messaging ;
12using Microsoft . Extensions . DependencyInjection ;
3+ using PCL . Neo . Messages ;
24using PCL . Neo . ViewModels ;
35using System ;
46using System . Collections . Generic ;
@@ -9,8 +11,8 @@ namespace PCL.Neo.Services;
911
1012public interface INavigationService
1113{
12- public event Action < NavigationEventArgs > ? Navigating ;
13- public event Action < NavigationEventArgs > ? Navigated ;
14+ // public event Action<NavigationMessage >? Navigating;
15+ // public event Action<NavigationMessage >? Navigated;
1416
1517 public ViewModelBase ? CurrentMainViewModel { get ; }
1618
@@ -30,28 +32,12 @@ public enum NavigationType
3032 Backward
3133}
3234
33- public class NavigationEventArgs (
34- ViewModelBase ? oldMainViewModel ,
35- ViewModelBase ? newMainViewModel ,
36- ViewModelBase ? oldSubViewModel ,
37- ViewModelBase ? newSubViewModel ,
38- NavigationType navigationType )
39- {
40- public bool IsMainViewModelChanged => oldMainViewModel != newMainViewModel ;
41- public ViewModelBase ? OldMainViewModel => oldMainViewModel ;
42- public ViewModelBase ? NewMainViewModel => newMainViewModel ;
43- public bool IsSubViewModelChanged => oldSubViewModel != newSubViewModel ;
44- public ViewModelBase ? OldSubViewModel => oldSubViewModel ;
45- public ViewModelBase ? NewSubViewModel => newSubViewModel ;
46- public NavigationType NavigationType => navigationType ;
47- }
48-
4935public class NavigationService ( IServiceProvider serviceProvider ) : INavigationService
5036{
5137 public IServiceProvider ServiceProvider { get ; } = serviceProvider ;
5238
53- public event Action < NavigationEventArgs > ? Navigating ;
54- public event Action < NavigationEventArgs > ? Navigated ;
39+ // public event Action<NavigationMessage >? Navigating;
40+ // public event Action<NavigationMessage >? Navigated;
5541
5642 // 导航历史记录
5743 private readonly LinkedList < ( Type ? , Type ? ) > _navigationHistory = [ ] ;
@@ -73,40 +59,50 @@ public class NavigationService(IServiceProvider serviceProvider) : INavigationSe
7359 /// <exception cref="InvalidOperationException"></exception>
7460 public async Task < ( ViewModelBase ? mainVm , ViewModelBase ? subVm ) > GoToAsync < T > ( ) where T : ViewModelBase
7561 {
76- // T 可为 `MainViewModel` 或 `SubViewModel`
77- // 根据 T 上附加的 attribute 判断
78- var mainAttr = typeof ( T ) . GetCustomAttribute < MainViewModelAttribute > ( ) ;
79- var subAttr = typeof ( T ) . GetCustomAttribute < SubViewModelAttribute > ( ) ;
80- if ( mainAttr is null && subAttr is null )
81- throw new InvalidOperationException (
82- $ "ViewModel { typeof ( T ) . Name } does not have a { nameof ( MainViewModelAttribute ) } or a { nameof ( SubViewModelAttribute ) } ") ;
83- if ( mainAttr is not null && subAttr is not null )
84- throw new InvalidOperationException (
85- $ "ViewModel { typeof ( T ) . Name } has both { nameof ( MainViewModelAttribute ) } and { nameof ( SubViewModelAttribute ) } ") ;
86-
87- Type ? mainVmType ;
88- Type ? subVmType ;
89- if ( mainAttr is not null )
62+ try
9063 {
91- mainVmType = typeof ( T ) ;
92- subVmType = mainAttr . DefaultSubViewModelType ;
64+ // T 可为 `MainViewModel` 或 `SubViewModel`
65+ // 根据 T 上附加的 attribute 判断
66+ var mainAttr = typeof ( T ) . GetCustomAttribute < MainViewModelAttribute > ( ) ;
67+ var subAttr = typeof ( T ) . GetCustomAttribute < SubViewModelAttribute > ( ) ;
68+ if ( mainAttr is null && subAttr is null )
69+ throw new InvalidOperationException (
70+ $ "ViewModel { typeof ( T ) . Name } does not have a { nameof ( MainViewModelAttribute ) } or a { nameof ( SubViewModelAttribute ) } ") ;
71+ if ( mainAttr is not null && subAttr is not null )
72+ throw new InvalidOperationException (
73+ $ "ViewModel { typeof ( T ) . Name } has both { nameof ( MainViewModelAttribute ) } and { nameof ( SubViewModelAttribute ) } ") ;
74+
75+ Type ? mainVmType ;
76+ Type ? subVmType ;
77+ if ( mainAttr is not null )
78+ {
79+ mainVmType = typeof ( T ) ;
80+ subVmType = mainAttr . DefaultSubViewModelType ;
81+ }
82+ else // if (subAttr is not null)
83+ {
84+ mainVmType = subAttr ! . MainViewModelType ;
85+ subVmType = typeof ( T ) ;
86+ }
87+
88+ var mainVm = CurrentMainViewModel ? . GetType ( ) == mainVmType
89+ ? CurrentMainViewModel
90+ : ( ViewModelBase ) ServiceProvider . GetRequiredService ( mainVmType ) ;
91+ var subVm = CurrentSubViewModel ? . GetType ( ) == subVmType
92+ ? CurrentSubViewModel
93+ : ( ViewModelBase ) ServiceProvider . GetRequiredService ( subVmType ) ;
94+
95+ await NavigateToAsync ( mainVm , subVm ) ;
96+
97+ return ( mainVm , subVm ) ;
9398 }
94- else // if (subAttr is not null )
99+ catch ( Exception ex )
95100 {
96- mainVmType = subAttr ! . MainViewModelType ;
97- subVmType = typeof ( T ) ;
101+ // TODO: logger
102+ Console . WriteLine ( $ "[ { nameof ( NavigationService ) } ] navigation failed: { ex } " ) ;
98103 }
99104
100- var mainVm = CurrentMainViewModel ? . GetType ( ) == mainVmType
101- ? CurrentMainViewModel
102- : ( ViewModelBase ) ServiceProvider . GetRequiredService ( mainVmType ) ;
103- var subVm = CurrentSubViewModel ? . GetType ( ) == subVmType
104- ? CurrentSubViewModel
105- : ( ViewModelBase ) ServiceProvider . GetRequiredService ( subVmType ) ;
106-
107- await NavigateToAsync ( mainVm , subVm ) ;
108-
109- return ( mainVm , subVm ) ;
105+ return ( null , null ) ;
110106 }
111107
112108 /// <summary>
@@ -117,16 +113,26 @@ public class NavigationService(IServiceProvider serviceProvider) : INavigationSe
117113 /// <returns>(MainViewModel, SubViewModel)</returns>
118114 public async Task < ( TM ? , TS ? ) > GoToAsync < TM , TS > ( ) where TM : ViewModelBase where TS : ViewModelBase
119115 {
120- var mainVm = CurrentMainViewModel ? . GetType ( ) == typeof ( TM )
121- ? CurrentMainViewModel as TM
122- : ServiceProvider . GetRequiredService < TM > ( ) ;
123- var subVm = CurrentSubViewModel ? . GetType ( ) == typeof ( TS )
124- ? CurrentSubViewModel as TS
125- : ServiceProvider . GetRequiredService < TS > ( ) ;
116+ try
117+ {
118+ var mainVm = CurrentMainViewModel ? . GetType ( ) == typeof ( TM )
119+ ? CurrentMainViewModel as TM
120+ : ServiceProvider . GetRequiredService < TM > ( ) ;
121+ var subVm = CurrentSubViewModel ? . GetType ( ) == typeof ( TS )
122+ ? CurrentSubViewModel as TS
123+ : ServiceProvider . GetRequiredService < TS > ( ) ;
126124
127- await NavigateToAsync ( mainVm , subVm ) ;
125+ await NavigateToAsync ( mainVm , subVm ) ;
128126
129- return ( mainVm , subVm ) ;
127+ return ( mainVm , subVm ) ;
128+ }
129+ catch ( Exception ex )
130+ {
131+ // TODO: logger
132+ Console . WriteLine ( $ "[{ nameof ( NavigationService ) } ] navigation failed: { ex } ") ;
133+ }
134+
135+ return ( null , null ) ;
130136 }
131137
132138 /// <summary>
@@ -139,25 +145,33 @@ protected async Task NavigateToAsync(ViewModelBase? main, ViewModelBase? sub,
139145 NavigationType navigationType = NavigationType . Forward )
140146 {
141147 var oldMainVm = CurrentMainViewModel ;
142- var oldSubVm = CurrentSubViewModel ;
148+ var oldSubVm = CurrentSubViewModel ;
143149
144- Navigating ? . Invoke ( new NavigationEventArgs (
150+ // Navigating?.Invoke(new NavigationMessage(
151+ // oldMainVm, main,
152+ // oldSubVm, sub,
153+ // navigationType));
154+ WeakReferenceMessenger . Default . Send ( new NavigationMessage (
145155 oldMainVm , main ,
146156 oldSubVm , sub ,
147- navigationType ) ) ;
157+ navigationType ) , NavigationMessage . Channels . Navigating ) ;
148158
149159 if ( navigationType == NavigationType . Forward )
150160 PushHistory (
151161 oldMainVm ? . GetType ( ) ?? null ,
152162 oldSubVm ? . GetType ( ) ?? null ) ;
153163
154164 CurrentMainViewModel = main ;
155- CurrentSubViewModel = sub ;
165+ CurrentSubViewModel = sub ;
156166
157- Navigated ? . Invoke ( new NavigationEventArgs (
167+ // Navigated?.Invoke(new NavigationMessage(
168+ // oldMainVm, main,
169+ // oldSubVm, sub,
170+ // navigationType));
171+ WeakReferenceMessenger . Default . Send ( new NavigationMessage (
158172 oldMainVm , main ,
159173 oldSubVm , sub ,
160- navigationType ) ) ;
174+ navigationType ) , NavigationMessage . Channels . Navigated ) ;
161175 }
162176
163177 /// <summary>
@@ -167,11 +181,21 @@ protected async Task NavigateToAsync(ViewModelBase? main, ViewModelBase? sub,
167181 /// <returns>(MainViewModel, SubViewModel)</returns>
168182 public async Task < ( ViewModelBase ? mainVm , ViewModelBase ? subVm ) > GoBackAsync ( )
169183 {
170- if ( ! TryPopHistory ( out var main , out var sub ) )
171- return ( CurrentMainViewModel , CurrentSubViewModel ) ;
184+ try
185+ {
186+ if ( ! TryPopHistory ( out var main , out var sub ) )
187+ return ( CurrentMainViewModel , CurrentSubViewModel ) ;
188+
189+ await NavigateToAsync ( main , sub , NavigationType . Backward ) ;
190+ return ( main , sub ) ;
191+ }
192+ catch ( Exception ex )
193+ {
194+ // TODO: logger
195+ Console . WriteLine ( $ "[{ nameof ( NavigationService ) } ] navigation failed: { ex } ") ;
196+ }
172197
173- await NavigateToAsync ( main , sub , NavigationType . Backward ) ;
174- return ( main , sub ) ;
198+ return ( null , null ) ;
175199 }
176200
177201 /// <summary>
0 commit comments