当你第一次选中一个单元格时,如何让WPF Datagrid选择一个单元格

时间:2011-12-05 18:45:36

标签: wpf datagrid

当我选择进入WPF Datagrid时,它会聚焦第一个单元格(带有一个矩形)但不选择它(蓝色)。如果我再次按Tab键,它会聚焦选择它。

我认为DataGridCell实际上有IsSelected = true,但它没有被涂成蓝色。我曾尝试使用数据网格和视觉状态进行黑客攻击,但是当你第一次选中时,我无法正确地重新绘制网格。

有没有人见过这个,你有解决方案吗?

重现的代码:

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; }
    }
}

单击TextBox,然后单击选项卡---未选择单元格

再次点击标签---选择单元格2

非常感谢任何帮助,谢谢。

更新

当SelectionUnit = FullRow时,我在下面显示的行中取得了一些成功,如果在创建时将SelectedIndex设置为0,则第一行 现在以蓝色选择。仍然需要一些工作来处理shift-tab等。但是仍然存在一个问题,因为当我将SelectionMode更改为extended并按下shift-downarrow时,第二行被选中但第一行未被选中(它们都应被选中) 。如果我再次选择行2 + 3,这是正确的,之后它会继续正常工作。

protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnIsKeyboardFocusWithinChanged(e);

        int oldIdx = this.SelectedIndex;
        this.SelectedIndex = -1;
        this.SelectedIndex = oldIdx;
    }

进一步更新:

通过设置private _selectionAnchor字段修复了该问题。 (感谢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);
        }
    }

3 个答案:

答案 0 :(得分:4)

你可以这样做。注册获得焦点事件,然后将原始源设置为选定项目。

<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>

然后在代码隐藏文件中:

    private void WPF_DataGrid_GotFocus(object sender, RoutedEventArgs e)
    {
        (e.OriginalSource as DataGridCell).IsSelected = true;

    }

我希望它有所帮助!

答案 1 :(得分:4)

我知道我的答案为时已晚,但这有助于其他导航到此网站。

经过大量的研究,我得到了如何在标签时选择元素的答案。 它真的很简单,在XAML中只有一行代码可以完成这个工作;

 <Style TargetType="{x:Type DataGridCell}">
     <Setter Property="IsTabStop" Value="False"/>
 </Style>

通过将IsTabStop设置为false,您告诉datagridcell的可视化树进入其模板并找到任何可聚焦的元素。如果它找到一些元素,那么它会聚焦该元素。

答案 2 :(得分:0)

如果CodeBehind是一个选项,则以下代码设置selectedItem:

private void CrashGrid_OnGotKeyboardFocus(object sender, RoutedEventArgs e)
{
    (DataGrid)e.Source.SelectedItem = (DataGrid)e.Source.CurrentCell.Item;
}