@@ -26,23 +26,44 @@ public static IDisposable Bind<TViewModel, TView, TProp>(
2626 Expression < Func < TViewModel , TProp > > vmProperty ,
2727 Expression < Func < TView , TProp > > viewProperty )
2828 where TViewModel : class
29- where TView : class , IViewForViewModel < TViewModel >
29+ where TView : IViewForViewModel < TViewModel >
3030 {
3131 return binderImplementation . Bind ( viewModel , view , vmProperty , viewProperty ) ;
3232 }
3333
34+ public static IDisposable Bind < TViewModel , TView , TProp > (
35+ this TView view ,
36+ TViewModel viewModel ,
37+ Expression < Func < TViewModel , TProp > > vmProperty )
38+ where TViewModel : class
39+ where TView : IViewForViewModel < TViewModel >
40+ {
41+ return binderImplementation . Bind ( viewModel , view , vmProperty , null ) ;
42+ }
43+
3444 public static IDisposable OneWayBind < TViewModel , TView , TProp > (
3545 this TView view ,
3646 TViewModel viewModel ,
3747 Expression < Func < TViewModel , TProp > > vmProperty ,
3848 Expression < Func < TView , TProp > > viewProperty ,
3949 Func < TProp > fallbackValue = null )
4050 where TViewModel : class
41- where TView : class , IViewForViewModel < TViewModel >
51+ where TView : IViewForViewModel < TViewModel >
4252 {
4353 return binderImplementation . OneWayBind ( viewModel , view , vmProperty , viewProperty , fallbackValue ) ;
4454 }
4555
56+ public static IDisposable OneWayBind < TViewModel , TView , TProp > (
57+ this TView view ,
58+ TViewModel viewModel ,
59+ Expression < Func < TViewModel , TProp > > vmProperty ,
60+ Func < TProp > fallbackValue = null )
61+ where TViewModel : class
62+ where TView : IViewForViewModel < TViewModel >
63+ {
64+ return binderImplementation . OneWayBind ( viewModel , view , vmProperty , null , fallbackValue ) ;
65+ }
66+
4667 public static IDisposable OneWayBind < TViewModel , TView , TProp , TOut > (
4768 this TView view ,
4869 TViewModel viewModel ,
@@ -51,11 +72,23 @@ public static IDisposable OneWayBind<TViewModel, TView, TProp, TOut>(
5172 Func < TProp , TOut > selector ,
5273 Func < TOut > fallbackValue = null )
5374 where TViewModel : class
54- where TView : class , IViewForViewModel < TViewModel >
75+ where TView : IViewForViewModel < TViewModel >
5576 {
5677 return binderImplementation . OneWayBind ( viewModel , view , vmProperty , viewProperty , selector , fallbackValue ) ;
5778 }
5879
80+ public static IDisposable OneWayBind < TViewModel , TView , TProp , TOut > (
81+ this TView view ,
82+ TViewModel viewModel ,
83+ Expression < Func < TViewModel , TProp > > vmProperty ,
84+ Func < TProp , TOut > selector ,
85+ Func < TOut > fallbackValue = null )
86+ where TViewModel : class
87+ where TView : IViewForViewModel < TViewModel >
88+ {
89+ return binderImplementation . OneWayBind ( viewModel , view , vmProperty , null , selector , fallbackValue ) ;
90+ }
91+
5992 public static IDisposable AsyncOneWayBind < TViewModel , TView , TProp , TOut > (
6093 this TView view ,
6194 TViewModel viewModel ,
@@ -64,10 +97,22 @@ public static IDisposable AsyncOneWayBind<TViewModel, TView, TProp, TOut>(
6497 Func < TProp , IObservable < TOut > > selector ,
6598 Func < TOut > fallbackValue = null )
6699 where TViewModel : class
67- where TView : class , IViewForViewModel < TViewModel >
100+ where TView : IViewForViewModel < TViewModel >
68101 {
69102 return binderImplementation . AsyncOneWayBind ( viewModel , view , vmProperty , viewProperty , selector , fallbackValue ) ;
70103 }
104+
105+ public static IDisposable AsyncOneWayBind < TViewModel , TView , TProp , TOut > (
106+ this TView view ,
107+ TViewModel viewModel ,
108+ Expression < Func < TViewModel , TProp > > vmProperty ,
109+ Func < TProp , IObservable < TOut > > selector ,
110+ Func < TOut > fallbackValue = null )
111+ where TViewModel : class
112+ where TView : IViewForViewModel < TViewModel >
113+ {
114+ return binderImplementation . AsyncOneWayBind ( viewModel , view , vmProperty , null , selector , fallbackValue ) ;
115+ }
71116 }
72117
73118 public interface IPropertyBinderImplementation
@@ -78,7 +123,7 @@ IDisposable Bind<TViewModel, TView, TProp>(
78123 Expression < Func < TViewModel , TProp > > vmProperty ,
79124 Expression < Func < TView , TProp > > viewProperty )
80125 where TViewModel : class
81- where TView : class , IViewForViewModel < TViewModel > ;
126+ where TView : IViewForViewModel < TViewModel > ;
82127
83128 IDisposable OneWayBind < TViewModel , TView , TProp > (
84129 TViewModel viewModel ,
@@ -87,7 +132,7 @@ IDisposable OneWayBind<TViewModel, TView, TProp>(
87132 Expression < Func < TView , TProp > > viewProperty ,
88133 Func < TProp > fallbackValue = null )
89134 where TViewModel : class
90- where TView : class , IViewForViewModel < TViewModel > ;
135+ where TView : IViewForViewModel < TViewModel > ;
91136
92137 IDisposable OneWayBind < TViewModel , TView , TProp , TOut > (
93138 TViewModel viewModel ,
@@ -97,7 +142,7 @@ IDisposable OneWayBind<TViewModel, TView, TProp, TOut>(
97142 Func < TProp , TOut > selector ,
98143 Func < TOut > fallbackValue = null )
99144 where TViewModel : class
100- where TView : class , IViewForViewModel < TViewModel > ;
145+ where TView : IViewForViewModel < TViewModel > ;
101146
102147 IDisposable AsyncOneWayBind < TViewModel , TView , TProp , TOut > (
103148 TViewModel viewModel ,
@@ -107,7 +152,7 @@ IDisposable AsyncOneWayBind<TViewModel, TView, TProp, TOut>(
107152 Func < TProp , IObservable < TOut > > selector ,
108153 Func < TOut > fallbackValue = null )
109154 where TViewModel : class
110- where TView : class , IViewForViewModel < TViewModel > ;
155+ where TView : IViewForViewModel < TViewModel > ;
111156 }
112157
113158 class PropertyBinderImplementation : IPropertyBinderImplementation
@@ -118,23 +163,31 @@ public IDisposable Bind<TViewModel, TView, TProp>(
118163 Expression < Func < TViewModel , TProp > > vmProperty ,
119164 Expression < Func < TView , TProp > > viewProperty )
120165 where TViewModel : class
121- where TView : class , IViewForViewModel < TViewModel >
166+ where TView : IViewForViewModel < TViewModel >
122167 {
123168 var ret = new CompositeDisposable ( ) ;
169+
170+ var vmPropChain = Reflection . ExpressionToPropertyNames ( vmProperty ) ;
171+ string [ ] viewPropChain ;
172+
173+ if ( viewProperty == null ) {
174+ viewPropChain = getDefaultViewPropChain ( view , vmPropChain ) ;
175+ } else {
176+ viewPropChain = Reflection . ExpressionToPropertyNames ( viewProperty ) ;
177+ }
178+
124179 var somethingChanged = Observable . Merge (
125180 Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty ) ,
126- view . WhenAny ( viewProperty , x => x . Value )
181+ view . WhenAnyDynamic ( viewPropChain , x => ( TProp ) x . Value )
127182 ) . Multicast ( new Subject < TProp > ( ) ) ;
128183
129- var vmPropChain = Reflection . ExpressionToPropertyNames ( vmProperty ) ;
130184 ret . Add ( somethingChanged . Where ( x => {
131185 TProp result ;
132186 if ( ! Reflection . TryGetValueForPropertyChain ( out result , view . ViewModel , vmPropChain ) )
133187 return false ;
134188 return EqualityComparer < TProp > . Default . Equals ( result , x ) != true ;
135189 } ) . Subscribe ( x => Reflection . SetValueToPropertyChain ( view . ViewModel , vmPropChain , x , false ) ) ) ;
136190
137- var viewPropChain = Reflection . ExpressionToPropertyNames ( viewProperty ) ;
138191 ret . Add ( somethingChanged . Where ( x => {
139192 TProp result ;
140193 if ( ! Reflection . TryGetValueForPropertyChain ( out result , view , viewPropChain ) )
@@ -160,11 +213,17 @@ public IDisposable OneWayBind<TViewModel, TView, TProp>(
160213 Expression < Func < TView , TProp > > viewProperty ,
161214 Func < TProp > fallbackValue = null )
162215 where TViewModel : class
163- where TView : class , IViewForViewModel < TViewModel >
216+ where TView : IViewForViewModel < TViewModel >
164217 {
165-
218+ if ( viewProperty == null ) {
219+ var viewPropChain = getDefaultViewPropChain ( view , Reflection . ExpressionToPropertyNames ( vmProperty ) ) ;
220+
221+ return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
222+ . Subscribe ( x => Reflection . SetValueToPropertyChain ( view , viewPropChain , x , false ) ) ;
223+ }
224+
166225 return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
167- . OneWayBind ( view , viewProperty , fallbackValue ) ;
226+ . BindTo ( view , viewProperty , fallbackValue ) ;
168227 }
169228
170229 public IDisposable OneWayBind < TViewModel , TView , TProp , TOut > (
@@ -175,11 +234,19 @@ public IDisposable OneWayBind<TViewModel, TView, TProp, TOut>(
175234 Func < TProp , TOut > selector ,
176235 Func < TOut > fallbackValue = null )
177236 where TViewModel : class
178- where TView : class , IViewForViewModel < TViewModel >
237+ where TView : IViewForViewModel < TViewModel >
179238 {
239+ if ( viewProperty == null ) {
240+ var viewPropChain = getDefaultViewPropChain ( view , Reflection . ExpressionToPropertyNames ( vmProperty ) ) ;
241+
242+ return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
243+ . Select ( selector )
244+ . Subscribe ( x => Reflection . SetValueToPropertyChain ( view , viewPropChain , x , false ) ) ;
245+ }
246+
180247 return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
181248 . Select ( selector )
182- . OneWayBind ( view , viewProperty , fallbackValue ) ;
249+ . BindTo ( view , viewProperty , fallbackValue ) ;
183250 }
184251
185252 public IDisposable AsyncOneWayBind < TViewModel , TView , TProp , TOut > (
@@ -190,11 +257,36 @@ public IDisposable AsyncOneWayBind<TViewModel, TView, TProp, TOut>(
190257 Func < TProp , IObservable < TOut > > selector ,
191258 Func < TOut > fallbackValue = null )
192259 where TViewModel : class
193- where TView : class , IViewForViewModel < TViewModel >
260+ where TView : IViewForViewModel < TViewModel >
194261 {
262+ if ( viewProperty == null ) {
263+ var viewPropChain = getDefaultViewPropChain ( view , Reflection . ExpressionToPropertyNames ( vmProperty ) ) ;
264+
265+ return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
266+ . SelectMany ( selector )
267+ . Subscribe ( x => Reflection . SetValueToPropertyChain ( view , viewPropChain , x , false ) ) ;
268+ }
269+
195270 return Reflection . ViewModelWhenAnyValue ( viewModel , view , vmProperty )
196271 . SelectMany ( selector )
197- . OneWayBind ( view , viewProperty , fallbackValue ) ;
272+ . BindTo ( view , viewProperty , fallbackValue ) ;
273+ }
274+
275+ static string [ ] getDefaultViewPropChain ( object view , string [ ] vmPropChain )
276+ {
277+ var vmPropertyName = vmPropChain . First ( ) ;
278+ var control = Reflection . GetValueFetcherForProperty ( view . GetType ( ) , vmPropertyName ) ( view ) ;
279+
280+ if ( control == null ) {
281+ throw new Exception ( String . Format ( "Tried to bind to control but it was null: {0}.{1}" , view . GetType ( ) . FullName ,
282+ vmPropertyName ) ) ;
283+ }
284+
285+ var defaultProperty = DefaultPropertyBinding . GetPropertyForControl ( control ) ;
286+ if ( defaultProperty == null ) {
287+ throw new Exception ( String . Format ( "Couldn't find a default property for type {0}" , control . GetType ( ) ) ) ;
288+ }
289+ return new [ ] { vmPropertyName , defaultProperty } ;
198290 }
199291 }
200292
@@ -210,12 +302,11 @@ public static class ObservableBindingMixins
210302 /// <param name="property">An expression representing the target
211303 /// property to set. This can be a child property (i.e. x.Foo.Bar.Baz).</param>
212304 /// <returns>An object that when disposed, disconnects the binding.</returns>
213- public static IDisposable OneWayBind < TTarget , TValue > (
305+ public static IDisposable BindTo < TTarget , TValue > (
214306 this IObservable < TValue > This ,
215307 TTarget target ,
216308 Expression < Func < TTarget , TValue > > property ,
217309 Func < TValue > fallbackValue = null )
218- where TTarget : class
219310 {
220311 var pn = Reflection . ExpressionToPropertyNames ( property ) ;
221312
0 commit comments