@@ -180,7 +180,8 @@ public bool CanFocus
180
180
if ( ! _canFocus && HasFocus )
181
181
{
182
182
// If CanFocus is set to false and this view has focus, make it leave focus
183
- HasFocus = false ;
183
+ // Set traverssingdown so we don't go back up the hierachy...
184
+ SetHasFocusFalse ( null , traversingDown : false ) ;
184
185
}
185
186
186
187
if ( _canFocus && ! HasFocus && Visible && SuperView is { Focused : null } )
@@ -296,7 +297,12 @@ internal bool RestoreFocus ()
296
297
297
298
if ( Focused is null && _previouslyFocused is { } && indicies . Contains ( _previouslyFocused ) )
298
299
{
299
- return _previouslyFocused . SetFocus ( ) ;
300
+ if ( _previouslyFocused . SetFocus ( ) )
301
+ {
302
+ return true ;
303
+ }
304
+
305
+ _previouslyFocused = null ;
300
306
}
301
307
302
308
return false ;
@@ -412,14 +418,14 @@ public bool SetFocus ()
412
418
/// other methods that
413
419
/// set or remove focus from a view.
414
420
/// </summary>
415
- /// <param name="previousFocusedView ">
416
- /// The previously focused view. If <see langword="null"/> there is no previously focused
421
+ /// <param name="currentFocusedView ">
422
+ /// The currently focused view. If <see langword="null"/> there is no previously focused
417
423
/// view.
418
424
/// </param>
419
425
/// <param name="traversingUp"></param>
420
426
/// <returns><see langword="true"/> if <see cref="HasFocus"/> was changed to <see langword="true"/>.</returns>
421
427
/// <exception cref="InvalidOperationException"></exception>
422
- private ( bool focusSet , bool cancelled ) SetHasFocusTrue ( View ? previousFocusedView , bool traversingUp = false )
428
+ private ( bool focusSet , bool cancelled ) SetHasFocusTrue ( View ? currentFocusedView , bool traversingUp = false )
423
429
{
424
430
Debug . Assert ( SuperView is null || ApplicationNavigation . IsInHierarchy ( SuperView , this ) ) ;
425
431
@@ -429,6 +435,11 @@ public bool SetFocus ()
429
435
return ( false , false ) ;
430
436
}
431
437
438
+ if ( currentFocusedView is { HasFocus : false } )
439
+ {
440
+ throw new ArgumentException ( "SetHasFocusTrue: currentFocusedView must HasFocus." ) ;
441
+ }
442
+
432
443
var thisAsAdornment = this as Adornment ;
433
444
View ? superViewOrParent = thisAsAdornment ? . Parent ?? SuperView ;
434
445
@@ -451,7 +462,7 @@ public bool SetFocus ()
451
462
452
463
bool previousValue = HasFocus ;
453
464
454
- bool cancelled = NotifyFocusChanging ( false , true , previousFocusedView , this ) ;
465
+ bool cancelled = NotifyFocusChanging ( false , true , currentFocusedView , this ) ;
455
466
456
467
if ( cancelled )
457
468
{
@@ -462,7 +473,7 @@ public bool SetFocus ()
462
473
// Any of them may cancel gaining focus. In which case we need to back out.
463
474
if ( superViewOrParent is { HasFocus : false } sv )
464
475
{
465
- ( bool focusSet , bool svCancelled ) = sv . SetHasFocusTrue ( previousFocusedView , true ) ;
476
+ ( bool focusSet , bool svCancelled ) = sv . SetHasFocusTrue ( currentFocusedView , true ) ;
466
477
467
478
if ( ! focusSet )
468
479
{
@@ -488,31 +499,33 @@ public bool SetFocus ()
488
499
489
500
if ( ! traversingUp )
490
501
{
491
- // Restore focus to the previously focused subview
502
+ // Restore focus to the previously focused subview, if any
492
503
if ( ! RestoreFocus ( ) )
493
504
{
494
- // Couldn't restore focus, so use Advance to navigate to the next focusable subview
495
- if ( ! AdvanceFocus ( NavigationDirection . Forward , null ) )
496
- {
497
- // Couldn't advance, so we're the most focused view in the application
498
- Application . Navigation ? . SetFocused ( this ) ;
499
- }
505
+ Debug . Assert ( _previouslyFocused is null ) ;
506
+ // Couldn't restore focus, so use Advance to navigate to the next focusable subview, if any
507
+ AdvanceFocus ( NavigationDirection . Forward , null ) ;
500
508
}
501
509
}
502
510
503
- if ( previousFocusedView is { HasFocus : true } && GetFocusChain ( NavigationDirection . Forward , TabStop ) . Contains ( previousFocusedView ) )
511
+ // Now make sure the old focused view loses focus
512
+ if ( currentFocusedView is { HasFocus : true } && GetFocusChain ( NavigationDirection . Forward , TabStop ) . Contains ( currentFocusedView ) )
504
513
{
505
- previousFocusedView . SetHasFocusFalse ( this ) ;
514
+ currentFocusedView . SetHasFocusFalse ( this ) ;
506
515
}
507
516
508
- _previouslyFocused = null ;
517
+ if ( _previouslyFocused is { } )
518
+ {
519
+ _previouslyFocused = null ;
520
+ }
509
521
510
522
if ( Arrangement . HasFlag ( ViewArrangement . Overlapped ) )
511
523
{
512
524
SuperView ? . MoveSubviewToEnd ( this ) ;
513
525
}
514
526
515
- NotifyFocusChanged ( HasFocus , previousFocusedView , this ) ;
527
+ // Focus work is done. Notify.
528
+ NotifyFocusChanged ( HasFocus , currentFocusedView , this ) ;
516
529
517
530
SetNeedsDisplay ( ) ;
518
531
@@ -527,6 +540,9 @@ public bool SetFocus ()
527
540
528
541
private bool NotifyFocusChanging ( bool currentHasFocus , bool newHasFocus , View ? currentFocused , View ? newFocused )
529
542
{
543
+ Debug . Assert ( currentFocused is null || currentFocused is { HasFocus : true } ) ;
544
+ Debug . Assert ( newFocused is null || newFocused is { CanFocus : true } ) ;
545
+
530
546
// Call the virtual method
531
547
if ( OnHasFocusChanging ( currentHasFocus , newHasFocus , currentFocused , newFocused ) )
532
548
{
@@ -543,6 +559,13 @@ private bool NotifyFocusChanging (bool currentHasFocus, bool newHasFocus, View?
543
559
return true ;
544
560
}
545
561
562
+ View ? appFocused = Application . Navigation ? . GetFocused ( ) ;
563
+
564
+ if ( appFocused == currentFocused )
565
+ {
566
+ Application . Navigation ? . SetFocused ( null ) ;
567
+ }
568
+
546
569
return false ;
547
570
}
548
571
@@ -586,8 +609,8 @@ private bool NotifyFocusChanging (bool currentHasFocus, bool newHasFocus, View?
586
609
/// focused.
587
610
/// </param>
588
611
/// <param name="traversingDown">
589
- /// Set to true to indicate method is being called recurively, traversing down the focus
590
- /// chain.
612
+ /// Set to true to traverse down the focus
613
+ /// chain only. If false, the method will attempt to AdvanceFocus on the superview or restorefocus on Application.Navigation.GetFocused() .
591
614
/// </param>
592
615
/// <exception cref="InvalidOperationException"></exception>
593
616
private void SetHasFocusFalse ( View ? newFocusedView , bool traversingDown = false )
@@ -598,53 +621,60 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
598
621
throw new InvalidOperationException ( "SetHasFocusFalse should not be called if the view does not have focus." ) ;
599
622
}
600
623
624
+ if ( newFocusedView is { HasFocus : false } )
625
+ {
626
+ throw new InvalidOperationException ( "SetHasFocusFalse new focused view does not have focus." ) ;
627
+ }
628
+
601
629
var thisAsAdornment = this as Adornment ;
602
630
View ? superViewOrParent = thisAsAdornment ? . Parent ?? SuperView ;
603
631
604
632
// If newFocusedVew is null, we need to find the view that should get focus, and SetFocus on it.
605
633
if ( ! traversingDown && newFocusedView is null )
606
634
{
607
- if ( superViewOrParent ? . _previouslyFocused is { } )
635
+ if ( superViewOrParent ? . _previouslyFocused is { CanFocus : true } )
608
636
{
609
- if ( superViewOrParent . _previouslyFocused != this )
637
+ if ( superViewOrParent . _previouslyFocused != this && superViewOrParent . _previouslyFocused . SetFocus ( ) )
610
638
{
611
- superViewOrParent ? . _previouslyFocused ? . SetFocus ( ) ;
612
-
613
639
// The above will cause SetHasFocusFalse, so we can return
640
+ Debug . Assert ( ! _hasFocus ) ;
614
641
return ;
615
642
}
616
643
}
617
644
618
- if ( superViewOrParent is { } )
645
+ if ( superViewOrParent is { CanFocus : true } )
619
646
{
620
647
if ( superViewOrParent . AdvanceFocus ( NavigationDirection . Forward , TabStop ) )
621
648
{
622
649
// The above will cause SetHasFocusFalse, so we can return
650
+ Debug . Assert ( ! _hasFocus ) ;
623
651
return ;
624
652
}
625
653
626
- newFocusedView = superViewOrParent ;
654
+ if ( superViewOrParent is { HasFocus : true , CanFocus : true } )
655
+ {
656
+ newFocusedView = superViewOrParent ;
657
+ }
627
658
}
628
659
629
- if ( Application . Navigation is { } && Application . Top is { } )
660
+ if ( Application . Navigation is { } && Application . Navigation . GetFocused ( ) is { CanFocus : true } )
630
661
{
631
662
// Temporarily ensure this view can't get focus
632
663
bool prevCanFocus = _canFocus ;
633
664
_canFocus = false ;
634
- bool restoredFocus = Application . Top ! . RestoreFocus ( ) ;
665
+ bool restoredFocus = Application . Navigation . GetFocused ( ) ! . RestoreFocus ( ) ;
635
666
_canFocus = prevCanFocus ;
636
667
637
668
if ( restoredFocus )
638
669
{
639
670
// The above caused SetHasFocusFalse, so we can return
671
+ Debug . Assert ( ! _hasFocus ) ;
640
672
return ;
641
673
}
642
674
}
643
-
644
675
// No other focusable view to be found. Just "leave" us...
645
676
}
646
677
647
-
648
678
// Before we can leave focus, we need to make sure that all views down the subview-hierarchy have left focus.
649
679
View ? mostFocused = MostFocused ;
650
680
@@ -665,15 +695,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
665
695
bottom = bottom . SuperView ;
666
696
}
667
697
668
- if ( bottom == this && bottom . SuperView is Adornment a )
669
- {
670
- //a.SetHasFocusFalse (newFocusedView, true);
671
-
672
- Debug . Assert ( _hasFocus ) ;
673
- }
674
-
675
698
Debug . Assert ( _hasFocus ) ;
676
-
677
699
}
678
700
679
701
if ( superViewOrParent is { } )
@@ -684,24 +706,16 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
684
706
bool previousValue = HasFocus ;
685
707
686
708
// Note, can't be cancelled.
687
- NotifyFocusChanging ( HasFocus , ! HasFocus , newFocusedView , this ) ;
709
+ NotifyFocusChanging ( HasFocus , ! HasFocus , this , newFocusedView ) ;
710
+
711
+ Debug . Assert ( _hasFocus ) ;
688
712
689
713
// Get whatever peer has focus, if any so we can update our superview's _previouslyMostFocused
690
714
View ? focusedPeer = superViewOrParent ? . Focused ;
691
715
692
716
// Set HasFocus false
693
717
_hasFocus = false ;
694
718
695
- if ( Application . Navigation is { } )
696
- {
697
- View ? appFocused = Application . Navigation . GetFocused ( ) ;
698
-
699
- if ( appFocused is { } || appFocused == this )
700
- {
701
- Application . Navigation . SetFocused ( newFocusedView ?? superViewOrParent ) ;
702
- }
703
- }
704
-
705
719
NotifyFocusChanged ( HasFocus , this , newFocusedView ) ;
706
720
707
721
if ( _hasFocus )
@@ -721,6 +735,11 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
721
735
722
736
private void NotifyFocusChanged ( bool newHasFocus , View ? previousFocusedView , View ? focusedVew )
723
737
{
738
+ if ( newHasFocus && focusedVew ? . Focused is null )
739
+ {
740
+ Application . Navigation ? . SetFocused ( focusedVew ) ;
741
+ }
742
+
724
743
// Call the virtual method
725
744
OnHasFocusChanged ( newHasFocus , previousFocusedView , focusedVew ) ;
726
745
0 commit comments