@@ -271,6 +271,102 @@ public void Indei_Validation_Updates_Data_Validation_When_Writing_To_Source()
271271 GC . KeepAlive ( data ) ;
272272 }
273273
274+ [ Fact ]
275+ public void Indei_Validation_Updates_Data_Validation_When_Writing_To_Source_OneWayToSource ( )
276+ {
277+ // Issue #8235: validation errors should be displayed for OneWayToSource bindings.
278+ var data = new IndeiViewModel ( ) ;
279+ var target = CreateTargetWithSource (
280+ data ,
281+ o => o . MustBePositive ,
282+ enableDataValidation : true ,
283+ mode : BindingMode . OneWayToSource ) ;
284+
285+ Assert . Equal ( 0 , data . MustBePositive ) ;
286+ AssertNoError ( target , TargetClass . IntProperty ) ;
287+
288+ target . Int = 5 ;
289+
290+ Assert . Equal ( 5 , data . MustBePositive ) ;
291+ AssertNoError ( target , TargetClass . IntProperty ) ;
292+
293+ target . Int = - 5 ;
294+
295+ Assert . Equal ( - 5 , data . MustBePositive ) ;
296+ AssertBindingError ( target , TargetClass . IntProperty , new DataValidationException ( "Must be positive" ) , BindingErrorType . DataValidationError ) ;
297+
298+ target . Int = 5 ;
299+
300+ Assert . Equal ( 5 , data . MustBePositive ) ;
301+ AssertNoError ( target , TargetClass . IntProperty ) ;
302+
303+ GC . KeepAlive ( data ) ;
304+ }
305+
306+ [ Fact ]
307+ public void DataAnnotations_Validation_Updates_Data_Validation_When_Writing_To_Source_OneWayToSource ( )
308+ {
309+ // Issue #8235: validation attributes should be displayed for OneWayToSource bindings.
310+ if ( ! BindingPlugins . DataValidators . Any ( x => x is DataAnnotationsValidationPlugin ) )
311+ BindingPlugins . DataValidators . Insert ( 0 , new DataAnnotationsValidationPlugin ( ) ) ;
312+
313+ var data = new DataAnnotationsViewModel ( ) ;
314+ var target = CreateTargetWithSource (
315+ data ,
316+ o => o . MaxLengthString ,
317+ enableDataValidation : true ,
318+ mode : BindingMode . OneWayToSource ) ;
319+
320+ target . String = "1234" ;
321+
322+ Assert . Equal ( "1234" , data . MaxLengthString ) ;
323+ AssertNoError ( target , TargetClass . StringProperty ) ;
324+
325+ target . String = "123456" ;
326+
327+ Assert . Equal ( "123456" , data . MaxLengthString ) ;
328+ AssertBindingError (
329+ target ,
330+ TargetClass . StringProperty ,
331+ new DataValidationException ( "Too long!" ) ,
332+ BindingErrorType . DataValidationError ) ;
333+
334+ GC . KeepAlive ( data ) ;
335+ }
336+
337+ [ Fact ]
338+ public void Conversion_Error_Is_Cleared_When_Value_Becomes_Valid_OneWayToSource ( )
339+ {
340+ // Issue #15378.
341+ var data = new ViewModel ( ) ;
342+ var target = CreateTargetWithSource (
343+ data ,
344+ o => o . DoubleValue ,
345+ targetProperty : TargetClass . ObjectProperty ,
346+ enableDataValidation : true ,
347+ mode : BindingMode . OneWayToSource ) ;
348+
349+ target . Object = 5.0 ;
350+
351+ Assert . Equal ( 5.0 , data . DoubleValue ) ;
352+ AssertNoError ( target , TargetClass . ObjectProperty ) ;
353+
354+ target . Object = null ;
355+
356+ AssertBindingError (
357+ target ,
358+ TargetClass . ObjectProperty ,
359+ new InvalidCastException ( "Could not convert '(null)' (null) to System.Double." ) ,
360+ BindingErrorType . DataValidationError ) ;
361+
362+ target . Object = 5.0 ;
363+
364+ Assert . Equal ( 5.0 , data . DoubleValue ) ;
365+ AssertNoError ( target , TargetClass . ObjectProperty ) ;
366+
367+ GC . KeepAlive ( data ) ;
368+ }
369+
274370 [ Fact ]
275371 public void Does_Not_Subscribe_To_Indei_Of_Intermediate_Object_In_Chain ( )
276372 {
@@ -445,6 +541,15 @@ public string? RequiredString
445541 get { return _requiredString ; }
446542 set { _requiredString = value ; RaisePropertyChanged ( ) ; }
447543 }
544+
545+ private string ? _maxLengthString ;
546+
547+ [ MaxLength ( 5 , ErrorMessage = "Too long!" ) ]
548+ public string ? MaxLengthString
549+ {
550+ get { return _maxLengthString ; }
551+ set { _maxLengthString = value ; RaisePropertyChanged ( ) ; }
552+ }
448553 }
449554
450555 private class IndeiDataAnnotationsViewModel : IndeiBase
0 commit comments