Knowledge base

IT is a great and exciting world to be in.
All who have passion for it will understand why we have created these pages.
Here we share our technical knowledge with you.
ProgrammingAICloudManagementMobileDB & AnalysisSafetyOtherArchitectureTips

WPF ListBox keyboard focus

Libor Bešenyi (Solution Architect)

Sometimes it is necessary to select an item in the listbox/combox within the keyboard focus (for example, when the user returns from modal window managed by this listbox).

GUI selection is very simple, if we want to select data from enumeration, we can use this code:

public enum SameEnum
{
        ValueA,
        Value2,
        Value3,
        Value4,
        AnotherValue
} // SameEnum

public MainWindow()
{
        InitializeComponent();

        ListBoxTest.ItemsSource = Enum.GetValues(typeof(SameEnum)).Cast<SameEnum>();               

        ListBoxTest.SelectedValue = SameEnum.Value4;
        ListBoxTest.Focus();
}

This will work, but when we push the arrow key (up/down), the item focus will be removed. We must select directly ListBoxItem for keyboard focus, not just value. ListBoxItem is embedded in ItemContainer, so we can hook event StatusChange (in run-time) – but we must remove the handler when it is done, so code is a bit horrible:

public static void SetValue<T>(Selector control, Func<T, bool> predicate)
{
        var item = control.ItemsSource.OfType<T>().FirstOrDefault(predicate);

        if (item != null && (control as ListBox != null))
        {
                EventHandler smernikNaEvent = null;

                smernikNaEvent = (object sender, EventArgs e) =>
                {
                        if ((control as ListBox).ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
                        {
                               int selectedIndex = (control as ListBox).SelectedIndex;
                               if (selectedIndex < 0)
                                                       control.ItemContainerGenerator.StatusChanged -= smernikNaEvent;
                               else
                               {
                                       ListBoxItem listBoxItem = (control as ListBox).ItemContainerGenerator.ContainerFromIndex(selectedIndex) as ListBoxItem;
                                       if (listBoxItem != null)
                                       {
                                               listBoxItem.Focus();
                                               control.ItemContainerGenerator.StatusChanged += null;

                                                control.ItemContainerGenerator.StatusChanged -= smernikNaEvent;
                                       } // if
                               } // else
                        } // if
                };

                 control.ItemContainerGenerator.StatusChanged += smernikNaEvent;
        } // if

         control.SelectedValue = control.ItemsSource.OfType<T>().FirstOrDefault(predicate);
}

public MainWindow()
{
        InitializeComponent();

        ListBoxTest.ItemsSource = Enum.GetValues(typeof(SameEnum)).Cast<SameEnum>();

        SetValue<SameEnum>(ListBoxTest, item => item == SameEnum.Value4);
}

In .Net 3.5, there can be a problem with GUI focusing called from control.Focus(), so there is a workaround using this routine:

public static void Focus(this Dispatcher dispatcher, UIElement element)
{
        dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate() { element.Focus(); }));
}

We must use this line:

Dispatcher.CurrentDispatcher.Focus(listBoxItem);

Instead of:

listBoxItem.Focus();

 

 

Find out more

ProgrammingTips

Quick start

1
Contact
Contact us for a free consultation on your business needs!
2
Analysis
After the discussion we will perform mapping of the processes and analyse the current state.
3
Proposal
You will receive variety of scenarios to choose from discribing different ways how to solve your issue.
Contact us