0

I'm trying to get (keyboard) focus work properly with an application of the following structure:

ItemsControl
  DataTemplate for Item
    ContentControl
      DataTemplate for Content (multiple, depending on type)
        Some container
          Different controls (mainly textbox or OK button should have focus)

On the root of each content template ("Some container"), I set FocusManager.FocusedElement to one control within the template. Of all the items in the ItemsControl, only one of the ContentControls is actually visible (the "current" one). So, basically, I make the first thing visible, the OK button in it has focus, user can press Enter to confirm. Then this one is hidden, the next one is shown, and its main control (e.g. a textbox) has focus, the user can press enter to confirm (small event handling to make enter in the textbox confirm the item) and so on.

When everything is done, the user can click a button in the toolbar to start over, making the first ContentControl visible again. But this time it doesn't have focus. I don't know who has focus, I'd like it to work like in the beginning. I tried to set focus to the just-shown ContentControl (which works, visible through the dashed line), but it won't set focus to it's children. Since I don't know which of the data templates is chosen (well, not without writing special code), I can't just set focus manually or through a binding to the child. Maybe I'm missing a simple thing at this point?

On the other hand, when the user manually clicks on the active ContentControl button or textbox, he can then confirm with enter, but then the ItemsControl seems to have focus, rather than the next item. I just can't get my head around this focus thing. Is there a simple solution? Do I have to write code to traverse the tree from the ContentControl to get the correct datatemplate? And then, can I just focus somehow the datatemplate or the control that is set as FocusedElement, or do I have to write code for each datatemplate separately?

OregonGhost
  • 23,359
  • 7
  • 71
  • 108

1 Answers1

0

You should implement an action which can be triggered from ViewModel to focus element when needed. Try this code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interactivity;
using System.Windows;

namespace Behaviors
{
    /// <summary>
    /// Action to focus target element, if invoked when target is not yet specified, will focus once the target is set
    /// </summary>
    public class FocusAction : TargetedTriggerAction<DependencyObject>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
        }
        protected override void Invoke(object parameter)
        {
            if (Target is UIElement)
            {
                if(!((UIElement)Target).IsKeyboardFocusWithin)
                    ((UIElement)Target).Focus();
            }
            else
                invokeOnConnect = true;
        }
        private bool invokeOnConnect = false;
        protected override void OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)
        {
            base.OnTargetChanged(oldTarget, newTarget);
            if (invokeOnConnect)
            {
                invokeOnConnect = false;
                Invoke(null);
            }
        }
    }
}

And then in WPF:

<DockPanel>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <nuib:FocusAction TargetName="title"/>
            </i:EventTrigger>
        <TextBlock x:Name="title"/>
</DockPanel>

namespaces are:

xmlns:nuib="clr-namespace:Behaviors;assembly=Nui" // for Action class
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" // .net library for interactivity
VidasV
  • 4,335
  • 1
  • 28
  • 50
  • Will try, but I'm not sure if that solves the problem. The point in time where I could trigger the change is the same as it is now (when one of the ContentControls becomes visible, I try to focus the right control, but it fails and sets focus to the previous ContentControl's control)... – OregonGhost Feb 06 '13 at 12:17