@@ -34,6 +34,11 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
34
34
return false ;
35
35
}
36
36
37
+ if ( RaiseAdvancingFocus ( direction , behavior ) )
38
+ {
39
+ return true ;
40
+ }
41
+
37
42
View ? focused = Focused ;
38
43
39
44
if ( focused is { } && focused . AdvanceFocus ( direction , behavior ) )
@@ -128,6 +133,11 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
128
133
if ( view . HasFocus )
129
134
{
130
135
// We could not advance
136
+ if ( view != this )
137
+ {
138
+ // Tell it to try the other way.
139
+ return view . RaiseAdvancingFocus ( direction == NavigationDirection . Forward ? NavigationDirection . Backward : NavigationDirection . Forward , behavior ) ;
140
+ }
131
141
return view == this ;
132
142
}
133
143
@@ -137,6 +147,52 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
137
147
return focusSet ;
138
148
}
139
149
150
+ private bool RaiseAdvancingFocus ( NavigationDirection direction , TabBehavior ? behavior )
151
+ {
152
+ // Call the virtual method
153
+ if ( OnAdvancingFocus ( direction , behavior ) )
154
+ {
155
+ // The event was cancelled
156
+ return true ;
157
+ }
158
+
159
+ var args = new AdvanceFocusEventArgs ( direction , behavior ) ;
160
+ AdvancingFocus ? . Invoke ( this , args ) ;
161
+
162
+ if ( args . Cancel )
163
+ {
164
+ // The event was cancelled
165
+ return true ;
166
+ }
167
+
168
+ return false ;
169
+ }
170
+
171
+ /// <summary>
172
+ /// Called when <see cref="View.AdvanceFocus"/> is about to advance focus.
173
+ /// </summary>
174
+ /// <remarks>
175
+ /// </remarks>
176
+ /// <returns>
177
+ /// <see langword="true"/>, if the focus advance is to be cancelled, <see langword="false"/>
178
+ /// otherwise.
179
+ /// </returns>
180
+ protected virtual bool OnAdvancingFocus ( NavigationDirection direction , TabBehavior ? behavior ) { return false ; }
181
+
182
+ /// <summary>
183
+ /// Raised when <see cref="View.AdvanceFocus"/> is about to advance focus.
184
+ /// </summary>
185
+ /// <remarks>
186
+ /// <para>
187
+ /// Cancel the event to prevent the focus from advancing.
188
+ /// </para>
189
+ /// <para>
190
+ /// Use <see cref="HasFocusChanged"/> to be notified after the focus has changed.
191
+ /// </para>
192
+ /// </remarks>
193
+ public event EventHandler < AdvanceFocusEventArgs > ? AdvancingFocus ;
194
+
195
+
140
196
/// <summary>Gets or sets a value indicating whether this <see cref="View"/> can be focused.</summary>
141
197
/// <remarks>
142
198
/// <para>
@@ -467,7 +523,7 @@ public bool SetFocus ()
467
523
468
524
bool previousValue = HasFocus ;
469
525
470
- bool cancelled = NotifyFocusChanging ( false , true , currentFocusedView , this ) ;
526
+ bool cancelled = RaiseFocusChanging ( false , true , currentFocusedView , this ) ;
471
527
472
528
if ( cancelled )
473
529
{
@@ -529,7 +585,7 @@ public bool SetFocus ()
529
585
}
530
586
531
587
// Focus work is done. Notify.
532
- NotifyFocusChanged ( HasFocus , currentFocusedView , this ) ;
588
+ RaiseFocusChanged ( HasFocus , currentFocusedView , this ) ;
533
589
534
590
SetNeedsDisplay ( ) ;
535
591
@@ -542,7 +598,7 @@ public bool SetFocus ()
542
598
return ( true , false ) ;
543
599
}
544
600
545
- private bool NotifyFocusChanging ( bool currentHasFocus , bool newHasFocus , View ? currentFocused , View ? newFocused )
601
+ private bool RaiseFocusChanging ( bool currentHasFocus , bool newHasFocus , View ? currentFocused , View ? newFocused )
546
602
{
547
603
Debug . Assert ( currentFocused is null || currentFocused is { HasFocus : true } ) ;
548
604
Debug . Assert ( newFocused is null || newFocused is { CanFocus : true } ) ;
@@ -750,7 +806,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
750
806
Debug . Assert ( _hasFocus ) ;
751
807
752
808
// Note, can't be cancelled.
753
- NotifyFocusChanging ( HasFocus , ! HasFocus , this , newFocusedView ) ;
809
+ RaiseFocusChanging ( HasFocus , ! HasFocus , this , newFocusedView ) ;
754
810
755
811
// Even though the change can't be cancelled, some listener may have changed the focus to another view.
756
812
if ( ! _hasFocus )
@@ -765,7 +821,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
765
821
// Set HasFocus false
766
822
_hasFocus = false ;
767
823
768
- NotifyFocusChanged ( HasFocus , this , newFocusedView ) ;
824
+ RaiseFocusChanged ( HasFocus , this , newFocusedView ) ;
769
825
770
826
if ( _hasFocus )
771
827
{
@@ -782,7 +838,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
782
838
SetNeedsDisplay ( ) ;
783
839
}
784
840
785
- private void NotifyFocusChanged ( bool newHasFocus , View ? previousFocusedView , View ? focusedVew )
841
+ private void RaiseFocusChanged ( bool newHasFocus , View ? previousFocusedView , View ? focusedVew )
786
842
{
787
843
if ( newHasFocus && focusedVew ? . Focused is null )
788
844
{
0 commit comments