diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs
index 74d67e0f4a..8a70ba201f 100644
--- a/src/Perspex.Controls/Control.cs
+++ b/src/Perspex.Controls/Control.cs
@@ -69,8 +69,7 @@ namespace Perspex.Controls
/// Defines the property.
///
public static readonly StyledProperty ContextMenuProperty =
- PerspexProperty.Register(nameof(ContextMenu));
-
+ PerspexProperty.Register(nameof(ContextMenu));
///
/// Event raised when an element wishes to be scrolled into view.
@@ -393,6 +392,15 @@ namespace Perspex.Controls
});
}
+ ///
+ /// Gets the element that recieves the focus adorner.
+ ///
+ /// The control that recieves the focus adorner.
+ protected virtual IControl GetTemplateFocusTarget()
+ {
+ return this;
+ }
+
///
/// Called when the control is added to a logical tree.
///
@@ -488,8 +496,13 @@ namespace Perspex.Controls
if (_focusAdorner != null)
{
- AdornerLayer.SetAdornedElement((Visual)_focusAdorner, this);
- adornerLayer.Children.Add(_focusAdorner);
+ var target = (Visual)GetTemplateFocusTarget();
+
+ if (target != null)
+ {
+ AdornerLayer.SetAdornedElement((Visual)_focusAdorner, target);
+ adornerLayer.Children.Add(_focusAdorner);
+ }
}
}
}
diff --git a/src/Perspex.Controls/Primitives/TemplatedControl.cs b/src/Perspex.Controls/Primitives/TemplatedControl.cs
index 0941864ae4..7c3d7dd7cf 100644
--- a/src/Perspex.Controls/Primitives/TemplatedControl.cs
+++ b/src/Perspex.Controls/Primitives/TemplatedControl.cs
@@ -74,6 +74,12 @@ namespace Perspex.Controls.Primitives
public static readonly StyledProperty TemplateProperty =
PerspexProperty.Register("Template");
+ ///
+ /// Defines the IsTemplateFocusTarget attached property.
+ ///
+ public static readonly AttachedProperty IsTemplateFocusTargetProperty =
+ PerspexProperty.RegisterAttached("IsTemplateFocusTarget");
+
///
/// Defines the routed event.
///
@@ -198,6 +204,33 @@ namespace Perspex.Controls.Primitives
set { SetValue(TemplateProperty, value); }
}
+ ///
+ /// Gets the value of the IsTemplateFocusTargetProperty attached property on a control.
+ ///
+ /// The control.
+ /// The property value.
+ ///
+ public bool GetIsTemplateFocusTarget(Control control)
+ {
+ return control.GetValue(IsTemplateFocusTargetProperty);
+ }
+
+ ///
+ /// Sets the value of the IsTemplateFocusTargetProperty attached property on a control.
+ ///
+ /// The control.
+ /// The property value.
+ ///
+ /// When a control is navigated to using the keyboard, a focus adorner is shown - usually
+ /// around the control itself. However if the TemplatedControl.IsTemplateFocusTarget
+ /// attached property is set to true on an element in the control template, then the focus
+ /// adorner will be shown around that control instead.
+ ///
+ public void SetIsTemplateFocusTarget(Control control, bool value)
+ {
+ control.SetValue(IsTemplateFocusTargetProperty, value);
+ }
+
///
public sealed override void ApplyTemplate()
{
@@ -224,6 +257,7 @@ namespace Perspex.Controls.Primitives
}
}
+ ///
protected sealed override IndexerDescriptor CreateBindingDescriptor(IndexerDescriptor source)
{
var result = base.CreateBindingDescriptor(source);
@@ -240,6 +274,20 @@ namespace Perspex.Controls.Primitives
return result;
}
+ ///
+ protected override IControl GetTemplateFocusTarget()
+ {
+ foreach (Control child in this.GetTemplateChildren())
+ {
+ if (GetIsTemplateFocusTarget(child))
+ {
+ return child;
+ }
+ }
+
+ return this;
+ }
+
///
/// Called when the control's template is applied.
///
diff --git a/src/Perspex.Controls/Templates/TemplateExtensions.cs b/src/Perspex.Controls/Templates/TemplateExtensions.cs
index 40672f873e..dbd5003b2d 100644
--- a/src/Perspex.Controls/Templates/TemplateExtensions.cs
+++ b/src/Perspex.Controls/Templates/TemplateExtensions.cs
@@ -12,7 +12,7 @@ namespace Perspex.Controls.Templates
{
public static class TemplateExtensions
{
- public static IEnumerable GetTemplateChildren(this ITemplatedControl control)
+ public static IEnumerable GetTemplateChildren(this ITemplatedControl control)
{
var visual = control as IVisual;
@@ -21,12 +21,12 @@ namespace Perspex.Controls.Templates
// TODO: This searches the whole descendent tree - it can stop when it exits the
// template.
return visual.GetVisualDescendents()
- .OfType()
+ .OfType()
.Where(x => x.TemplatedParent == control);
}
else
{
- return Enumerable.Empty();
+ return Enumerable.Empty();
}
}
}
diff --git a/src/Perspex.Themes.Default/TreeViewItem.paml b/src/Perspex.Themes.Default/TreeViewItem.paml
index 5758f598bb..9df1ec1545 100644
--- a/src/Perspex.Themes.Default/TreeViewItem.paml
+++ b/src/Perspex.Themes.Default/TreeViewItem.paml
@@ -11,18 +11,12 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
+ TemplatedControl.IsTemplateFocusTarget="True"
Grid.Column="1">
-