Created
November 1, 2012 22:31
-
-
Save dbeattie71/3997130 to your computer and use it in GitHub Desktop.
KeyboardTabBehavior to work with Telerik TextBox and PasswordBox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class KeyboardTabBehavior : Behavior<UIElement> | |
{ | |
private KeyboardTabHelper _keyboardTabHelper; | |
protected override void OnAttached() | |
{ | |
base.OnAttached(); | |
_keyboardTabHelper = new KeyboardTabHelper(AssociatedObject); | |
} | |
protected override void OnDetaching() | |
{ | |
base.OnDetaching(); | |
_keyboardTabHelper.OnDetach(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class KeyboardTabHelper | |
{ | |
private readonly UIElement _associatedObject; | |
private readonly PhoneApplicationPage _phoneApplicationPage; | |
private List<TabControl> _tabControls; | |
private TabControl _lastTabControl; | |
public KeyboardTabHelper(UIElement associatedObject) | |
{ | |
_associatedObject = associatedObject; | |
_phoneApplicationPage = | |
((PhoneApplicationFrame) Application.Current.RootVisual).Content as PhoneApplicationPage; | |
if (_phoneApplicationPage == null) | |
throw new NullReferenceException("_phoneApplicationPage"); | |
_phoneApplicationPage.Loaded += OnPhoneApplicationPageOnLoaded; | |
_associatedObject.KeyDown += OnAssociatedObjectKeyDown; | |
} | |
public void OnDetach() | |
{ | |
UnRegisterTabControlEvents(_tabControls); | |
_associatedObject.KeyDown -= OnAssociatedObjectKeyDown; | |
_phoneApplicationPage.Loaded -= OnPhoneApplicationPageOnLoaded; | |
} | |
private void OnPhoneApplicationPageOnLoaded(object sender, RoutedEventArgs args) | |
{ | |
FindTabControls((UIElement) sender); | |
} | |
private void FindTabControls(UIElement layoutRoot) | |
{ | |
_tabControls = GetChildren(layoutRoot).OfType<Control>() | |
.Where(c => c.IsTabStop && c.TabIndex != int.MaxValue) | |
.OrderBy(c => c.TabIndex) | |
.Select(c => new TabControl {Control = c, KeyboardFocusedControl = null}) | |
.ToList(); | |
RegisterTabControlEvents(_tabControls); | |
if (_tabControls.Count > 0) | |
_lastTabControl = _tabControls[_tabControls.Count - 1]; | |
} | |
private void RegisterTabControlEvents(IEnumerable<TabControl> tabControls) | |
{ | |
tabControls.Apply(tabControl => { tabControl.Control.GotFocus += OnTabbedControlGotFocus; }); | |
} | |
private void UnRegisterTabControlEvents(IEnumerable<TabControl> tabbedControls) | |
{ | |
tabbedControls.Apply(tabControl => { tabControl.Control.GotFocus -= OnTabbedControlGotFocus; }); | |
} | |
private void OnTabbedControlGotFocus(object sender, RoutedEventArgs e) | |
{ | |
var tabControlWithFocus = _tabControls.FirstOrDefault(t => t.Control == sender); | |
if (tabControlWithFocus == null) | |
return; | |
tabControlWithFocus.KeyboardFocusedControl = e.OriginalSource as Control; | |
} | |
private void OnAssociatedObjectKeyDown(object sender, KeyEventArgs e) | |
{ | |
if (e.Key == Key.Enter) | |
HandleReturnKey(); | |
} | |
private void HandleReturnKey() | |
{ | |
var controlWithFocus = FocusManager.GetFocusedElement() as Control; | |
if (controlWithFocus == null) | |
return; | |
var tabCcontrolWithFocus = FindTabControlWithFocus(controlWithFocus); | |
if (tabCcontrolWithFocus == null) | |
return; | |
SetFocusOnNextControl(tabCcontrolWithFocus); | |
} | |
private TabControl FindTabControlWithFocus(Control controlWithFocus) | |
{ | |
return _tabControls.FirstOrDefault(tabControl => tabControl.Control == controlWithFocus | |
|| tabControl.KeyboardFocusedControl == controlWithFocus); | |
} | |
private void SetFocusOnNextControl(TabControl tabControl) | |
{ | |
if (_lastTabControl.KeyboardFocusedControl == tabControl.KeyboardFocusedControl) | |
_phoneApplicationPage.Focus(); | |
else | |
{ | |
var nextControl = _tabControls | |
.FirstOrDefault(c => c.Control.TabIndex > tabControl.Control.TabIndex); | |
var wasFocusSet = false; | |
if (nextControl != null) | |
wasFocusSet = nextControl.Control.Focus(); | |
if (!wasFocusSet) | |
SetFocusOnNextControl(nextControl); | |
} | |
} | |
private static IEnumerable<DependencyObject> GetChildren(DependencyObject root) | |
{ | |
var children = new List<DependencyObject> {root}; | |
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) | |
children.AddRange(GetChildren(VisualTreeHelper.GetChild(root, i))); | |
return children; | |
} | |
private class TabControl | |
{ | |
public Control Control { get; set; } | |
public Control KeyboardFocusedControl { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment