5
5
6
6
using System ;
7
7
using System . Reactive ;
8
+ using System . Reactive . Disposables ;
8
9
using System . Reactive . Linq ;
9
10
using System . Reactive . Subjects ;
10
11
using System . Windows ;
@@ -27,22 +28,22 @@ namespace ReactiveUI
27
28
public class ViewModelViewHost : TransitioningContentControl , IViewFor , IEnableLogger , IDisposable
28
29
{
29
30
/// <summary>
30
- /// The view model dependency property.
31
+ /// The default content dependency property.
31
32
/// </summary>
32
- public static readonly DependencyProperty ViewModelProperty =
33
- DependencyProperty . Register ( "ViewModel" , typeof ( object ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( null , SomethingChanged ) ) ;
33
+ public static readonly DependencyProperty DefaultContentProperty =
34
+ DependencyProperty . Register ( nameof ( DefaultContent ) , typeof ( object ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( null ) ) ;
34
35
35
36
/// <summary>
36
- /// The default content dependency property.
37
+ /// The view model dependency property.
37
38
/// </summary>
38
- public static readonly DependencyProperty DefaultContentProperty =
39
- DependencyProperty . Register ( "DefaultContent" , typeof ( object ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( null , SomethingChanged ) ) ;
39
+ public static readonly DependencyProperty ViewModelProperty =
40
+ DependencyProperty . Register ( nameof ( ViewModel ) , typeof ( object ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( null , SomethingChanged ) ) ;
40
41
41
42
/// <summary>
42
43
/// The view contract observable dependency property.
43
44
/// </summary>
44
45
public static readonly DependencyProperty ViewContractObservableProperty =
45
- DependencyProperty . Register ( " ViewContractObservable" , typeof ( IObservable < string > ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( Observable < string > . Default ) ) ;
46
+ DependencyProperty . Register ( nameof ( ViewContractObservable ) , typeof ( IObservable < string > ) , typeof ( ViewModelViewHost ) , new PropertyMetadata ( Observable < string > . Default , SomethingChanged ) ) ;
46
47
47
48
private readonly Subject < Unit > _updateViewModel = new Subject < Unit > ( ) ;
48
49
private string _viewContract ;
@@ -57,17 +58,14 @@ public ViewModelViewHost()
57
58
DefaultStyleKey = typeof ( ViewModelViewHost ) ;
58
59
#endif
59
60
60
- if ( ModeDetector . InUnitTestRunner ( ) ) // NB: InUnitTestRunner also returns true in Design Mode
61
+ if ( ModeDetector . InUnitTestRunner ( ) )
61
62
{
62
63
ViewContractObservable = Observable < string > . Never ;
64
+
65
+ // NB: InUnitTestRunner also returns true in Design Mode
63
66
return ;
64
67
}
65
68
66
- var vmAndContract = Observable . CombineLatest (
67
- this . WhenAnyValue ( x => x . ViewModel ) ,
68
- this . WhenAnyObservable ( x => x . ViewContractObservable ) ,
69
- ( vm , contract ) => new { ViewModel = vm , Contract = contract , } ) ;
70
-
71
69
var platform = Locator . Current . GetService < IPlatformOperations > ( ) ;
72
70
Func < string > platformGetter = ( ) => default ( string ) ;
73
71
@@ -87,32 +85,15 @@ public ViewModelViewHost()
87
85
. StartWith ( platformGetter ( ) )
88
86
. DistinctUntilChanged ( ) ;
89
87
90
- this . WhenActivated ( d =>
91
- {
92
- d ( vmAndContract . Subscribe ( x =>
93
- {
94
- if ( x . ViewModel == null )
95
- {
96
- Content = DefaultContent ;
97
- return ;
98
- }
99
-
100
- var viewLocator = ViewLocator ?? ReactiveUI . ViewLocator . Current ;
101
- var view = viewLocator . ResolveView ( x . ViewModel , x . Contract ) ?? viewLocator . ResolveView ( x . ViewModel , null ) ;
102
-
103
- if ( view == null )
104
- {
105
- throw new Exception ( $ "Couldn't find view for '{ x . ViewModel } '.") ;
106
- }
107
-
108
- view . ViewModel = x . ViewModel ;
109
- Content = view ;
110
- } ) ) ;
111
-
112
- d ( this . WhenAnyObservable ( x => x . ViewContractObservable )
113
- . ObserveOn ( RxApp . MainThreadScheduler )
114
- . Subscribe ( x => _viewContract = x ) ) ;
115
- } ) ;
88
+ var contractChanged = _updateViewModel . Select ( _ => ViewContractObservable ) . Switch ( ) ;
89
+ var viewModelChanged = _updateViewModel . Select ( _ => ViewModel ) ;
90
+
91
+ var vmAndContract = contractChanged . CombineLatest ( viewModelChanged , ( contract , vm ) => new { ViewModel = vm , Contract = contract } ) ;
92
+
93
+ vmAndContract . Subscribe ( x => ResolveViewForViewModel ( x . ViewModel , x . Contract ) ) ;
94
+ contractChanged
95
+ . ObserveOn ( RxApp . MainThreadScheduler )
96
+ . Subscribe ( x => _viewContract = x ) ;
116
97
}
117
98
118
99
/// <summary>
@@ -186,5 +167,26 @@ private static void SomethingChanged(DependencyObject dependencyObject, Dependen
186
167
{
187
168
( ( ViewModelViewHost ) dependencyObject ) . _updateViewModel . OnNext ( Unit . Default ) ;
188
169
}
170
+
171
+ private void ResolveViewForViewModel ( object viewModel , string contract )
172
+ {
173
+ if ( viewModel == null )
174
+ {
175
+ Content = DefaultContent ;
176
+ return ;
177
+ }
178
+
179
+ var viewLocator = ViewLocator ?? ReactiveUI . ViewLocator . Current ;
180
+ var viewInstance = viewLocator . ResolveView ( viewModel , contract ) ?? viewLocator . ResolveView ( viewModel , null ) ;
181
+
182
+ if ( viewInstance == null )
183
+ {
184
+ throw new Exception ( $ "The { nameof ( ViewModelViewHost ) } could not find a valid view for the view model of type { viewModel . GetType ( ) } and value { viewModel } .") ;
185
+ }
186
+
187
+ viewInstance . ViewModel = viewModel ;
188
+
189
+ Content = viewInstance ;
190
+ }
189
191
}
190
192
}
0 commit comments