diff --git a/Perspex.Controls/Presenters/TextPresenter.cs b/Perspex.Controls/Presenters/TextPresenter.cs index a8c97e5d02..3f4ca97322 100644 --- a/Perspex.Controls/Presenters/TextPresenter.cs +++ b/Perspex.Controls/Presenters/TextPresenter.cs @@ -286,6 +286,16 @@ namespace Perspex.Controls.Presenters { goto default; } + else if ((modifiers & ModifierKeys.Shift) == 0) + { + // TODO: Keyboard navigation should be moved to InputElement. This is just a + // hack to get TextBox tab navigation working. + KeyboardNavigation.MoveNext((IInputElement)this.TemplatedParent); + } + else + { + KeyboardNavigation.MovePrevious((IInputElement)this.TemplatedParent); + } break; diff --git a/Perspex.Controls/TextBox.cs b/Perspex.Controls/TextBox.cs index 47eef390fb..e0b8f864ce 100644 --- a/Perspex.Controls/TextBox.cs +++ b/Perspex.Controls/TextBox.cs @@ -8,7 +8,11 @@ namespace Perspex.Controls { using System; using System.Reactive.Linq; + using Perspex.Controls.Presenters; using Perspex.Controls.Primitives; + using Perspex.Controls.Templates; + using Perspex.Input; + using Perspex.Interactivity; public class TextBox : TemplatedControl { @@ -33,6 +37,13 @@ namespace Perspex.Controls public static readonly PerspexProperty TextWrappingProperty = TextBlock.TextWrappingProperty.AddOwner(); + private TextPresenter presenter; + + static TextBox() + { + FocusableProperty.OverrideDefaultValue(typeof(TextBox), true); + } + public TextBox() { var canScrollHorizontally = this.GetObservable(AcceptsReturnProperty) @@ -100,5 +111,17 @@ namespace Perspex.Controls var length = (text != null) ? text.Length : 0; return Math.Max(0, Math.Min(length, value)); } + + protected override void OnTemplateApplied() + { + this.presenter = this.GetTemplateChild("textPresenter"); + } + + protected override void OnGotFocus(RoutedEventArgs e) + { + // TODO: There needs to be a better way of setting focus to a templated child. + base.OnGotFocus(e); + FocusManager.Instance.Focus(this.presenter); + } } } diff --git a/Perspex.Input/KeyboardNavigation.cs b/Perspex.Input/KeyboardNavigation.cs new file mode 100644 index 0000000000..e9f43fd8ec --- /dev/null +++ b/Perspex.Input/KeyboardNavigation.cs @@ -0,0 +1,49 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Input +{ + using System.Linq; + using Perspex.VisualTree; + + /// + /// TODO: This class is a temporary stop-gap just to add tab handling. Should be replaced + /// with something better thought out and testable etc. + /// + public static class KeyboardNavigation + { + public static void MoveNext(IInputElement element) + { + var siblings = element.GetVisualSiblings().OfType() + .Where(x => x.Focusable) + .SkipWhile(x => x != element) + .Skip(1); + + var next = siblings.FirstOrDefault(); + + if (next != null) + { + FocusManager.Instance.Focus(next); + } + } + + public static void MovePrevious(IInputElement element) + { + var siblings = element.GetVisualSiblings().OfType() + .Where(x => x.Focusable) + .Reverse() + .SkipWhile(x => x != element) + .Skip(1); + + var next = siblings.FirstOrDefault(); + + if (next != null) + { + FocusManager.Instance.Focus(next); + } + } + } +} diff --git a/Perspex.Input/Perspex.Input.csproj b/Perspex.Input/Perspex.Input.csproj index 3d38054027..4a157110ca 100644 --- a/Perspex.Input/Perspex.Input.csproj +++ b/Perspex.Input/Perspex.Input.csproj @@ -72,6 +72,7 @@ + diff --git a/Perspex.Themes.Default/TextBoxStyle.cs b/Perspex.Themes.Default/TextBoxStyle.cs index bc0f045137..ffbabace98 100644 --- a/Perspex.Themes.Default/TextBoxStyle.cs +++ b/Perspex.Themes.Default/TextBoxStyle.cs @@ -55,6 +55,7 @@ namespace Perspex.Themes.Default [~ScrollViewer.VerticalScrollBarVisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty], Content = new TextPresenter { + Id = "textPresenter", [~TextPresenter.AcceptsReturnProperty] = control[~TextBox.AcceptsReturnProperty], [~TextPresenter.AcceptsTabProperty] = control[~TextBox.AcceptsTabProperty], [~TextPresenter.CaretIndexProperty] = control[~TextBox.CaretIndexProperty],