Reputation: 41676
I have a window with a single ListView:
It looks as if the focus is on the first element in the list. When I press Down, I expect the focus to move to the second line, but it stays at this element. The dashed border moves though, from the whole list to the first list item:
At this point, pressing Down moves the focus down as expected.
I already did a bit of research on how to get the keyboard focus right from the beginning, but I didn't succeed. In the properties of a ListView
, there are AnchorItem
and FocusedInfo
, which both look promising, but they are not directly accessible, so I don't know the correct way to set them.
Here is my current XAML code:
<Window x:Class="CSharp_Playground.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CSharp_Playground"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:Model />
</Window.DataContext>
<ListView Name="Persons" ItemsSource="{Binding Persons}" SelectionMode="Single" />
</Window>
And the corresponding C# code:
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace CSharp_Playground
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Persons.SelectedIndex = 0;
Persons.Focus();
}
}
public class Model
{
public IEnumerable<string> Persons { get; } = new ObservableCollection<string>(new []{"1","2","3"});
}
}
Upvotes: 0
Views: 226
Reputation: 919
The trick seems to be to explicitly set the focus to the item container of the first item in the ListView. I found a good explanation here.
Short summary of that blog post:
Because the items aren't available directly after creating the ListView focusing has to happen after all items are generated in the background. So, attach to the StatusChanged
event of the ItemContainerGenerator
:
Persons.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
And in the event handler, set the focus after everything has finished generating:
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (Persons.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
int index = Persons.SelectedIndex;
if (index >= 0)
((ListViewItem)Persons.ItemContainerGenerator.ContainerFromIndex(index)).Focus();
}
}
This solution isn't as simple as I hoped it would be but it worked for me.
Upvotes: 1