Reputation: 591
When I tab into the WPF Datagrid it focuses the first cell (with a rectangle) but does not select it (in blue). If I press tab again it focuses and selects it.
I think the DataGridCell actually has IsSelected=true, but it is not being painted in blue. I have tried hacking around with the datagrid and visual-states but I can't make it repaint the grid correctly when you first tab in.
Has anyone seen this before and do you have a solution?
code to reproduce:
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Width="100"/>
<DataGrid SelectionMode="Single" SelectionUnit="Cell"
ItemsSource="{Binding MyItems}" AutoGenerateColumns="True"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Collections.Generic;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyItems.Add(new Thingy() { Name = "Frank", Age = 34 });
MyItems.Add(new Thingy() { Name = "Jim", Age = 43 });
MyItems.Add(new Thingy() { Name = "Bob", Age = 56 });
MyItems.Add(new Thingy() { Name = "Harry", Age = 23 });
DataContext = this;
}
private List<Thingy> _myItems = new List<Thingy>();
public List<Thingy> MyItems
{
get { return _myItems; }
}
}
public class Thingy
{
public string Name { get; set; }
public int Age { get; set; }
}
}
click on the TextBox, then hit tab --- cell 1 is not selected
hit tab again --- cell 2 is selected
Any help is much appreciated, thanks.
Update:
When SelectionUnit=FullRow, I have had some success along the lines shown below, if SelectedIndex is set to 0 upon creation the first row is now selected in blue. It still needs some work to cope with shift-tab etc. There is still a problem though because when I change the SelectionMode to extended and press shift-downarrow the second row gets selected but the first row gets unselected (they should both be selected). If I do it again rows 2+3 are selected which is correct and it continues to work ok after that.
protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e)
{
base.OnIsKeyboardFocusWithinChanged(e);
int oldIdx = this.SelectedIndex;
this.SelectedIndex = -1;
this.SelectedIndex = oldIdx;
}
Further Update:
Fixed that issue by setting the private _selectionAnchor field. (Thanks ILSpy)
protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e)
{
base.OnIsKeyboardFocusWithinChanged(e);
this.SelectedIndex = -1;
this.SelectedIndex = 0;
SelectionAnchor = SelectedCells[0];
}
protected DataGridCellInfo? SelectionAnchor
{
get
{
return typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this) as DataGridCellInfo?;
}
set
{
typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value);
}
}
Upvotes: 10
Views: 4538
Reputation: 4206
If CodeBehind is an option the following code sets the selectedItem:
private void CrashGrid_OnGotKeyboardFocus(object sender, RoutedEventArgs e)
{
(DataGrid)e.Source.SelectedItem = (DataGrid)e.Source.CurrentCell.Item;
}
Upvotes: 0
Reputation:
I know my answer is too late but it would help other navigating to this site.
After lot of research, I got the answer on how to select the element while tabbing. It was really easy and was a single line of code in XAML that did the trick;
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="IsTabStop" Value="False"/>
</Style>
By setting IsTabStop
to false you are telling the datagridcell's visual tree to go inside its template and find any element that is focus able. If it finds some element then it focuses that element.
Upvotes: 5
Reputation: 2489
You can do like this. Register for a got focus event and then set the original source as selected item.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Width="100"/>
<DataGrid SelectionMode="Single" SelectionUnit="Cell"
ItemsSource="{Binding MyItems}" AutoGenerateColumns="True"
GotFocus="WPF_DataGrid_GotFocus" />
</StackPanel>
</Window>
Then in the code behind file :
private void WPF_DataGrid_GotFocus(object sender, RoutedEventArgs e)
{
(e.OriginalSource as DataGridCell).IsSelected = true;
}
I hope it helps!
Upvotes: 4