0

这个问题一般适用于标准的DataGridView。由于某种原因,它总是会在排序后选择一个单元格,即使在用户单击列标题对 DataGridView 进行排序时没有选择单元格(选择已清除)。为了解释为什么我真的不想要这个,我需要提供更多关于我的项目的背景信息。

我需要扩展 DataGridView 的功能,同时保持数据绑定不变。首先,我需要将数据组织成可扩展/可折叠的组。稍后,将添加已经专门为 DataGridView(由其他人)编写的其他功能。这意味着我没有使用不是围绕 DataGridView 构建的第三方网格组件的自由。

因此,我决定使用 HotDog (Robert Verpalen) 编写的 DataGridViewGrouper 组件,请参阅此链接以获取他的代码。在这个组件中,折叠行通过将其可见属性设置为 false 来隐藏。

原则上它是有效的,直到我在选择组行之一后尝试对数据进行排序。在这种情况下,它会引发错误:ArgumentOutOfRangeException。我想我会采取捷径来解决这个问题并补充说:

private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (dataGridViewGrouper1.CurrentRowIsGroupRow)
    {
        dataGridView1.ClearSelection();
    }
}

用户没有理由必须能够选择组行之一,并且清除他们的选择可以消除我在尝试排序时遇到的错误。但是,排序后,总会有一个单元格被选中;即使选择在排序之前被清除。

我添加了一个 CellMouseDown 事件来跟踪在排序之前最后选择了哪个单元格,以便在排序之后我可以再次选择同一个单元格(而不是恰好位于同一行索引的单元格)。

private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.RowIndex == -1)
    {
        if (dataGridView1.SelectedCells.Count == 0) { return;  }
        selected = dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString();
    }
}

如果没有选定的单元格,我会从此方法返回(毕竟没有什么要记住的)。如果在最后一次选择组行之后尝试排序,则确实会发生此返回,这意味着我尝试清除该选择是成功的。

但是,在这种情况下,排序后仍会选择一个单元格。这是组中某处看似随机选择的单元格。我怀疑它与在清除选择之前选择的单元格的位置有关。这会导致相当烦人的行为,例如屏幕跳转到此选定单元格的位置(几百行之外)或折叠组中的不可见行在被选中时变得可见。

我不知道在哪个事件中选择了单元格。我试图在排序之前跟踪选择了哪个组行,以便以后可以选择其他内容,如有必要,使该组中的所有行再次不可见,但我没有管理。我也觉得这不是解决这个问题的正确方法。

同样,在进入排序操作之前使用循环选择最接近的可见数据单元格而不是清除选择,这似乎不是一个很好的解决方案。特别是因为当所有组都折叠时我仍然会遇到问题(没有可见的数据行)。

我真正想要的(我认为)是在排序后停止选择一个单元格,如果在排序之前没有选择一个单元格。有人可以帮我吗?

4

2 回答 2

3

每次调用 Sort() 时,DataBindingCompleted 事件也会上升(非常烦人),即使您在 DataGridView 中的选择被清除,BindingContext[dataGridView1.DataSource].Position 不会改变,并且您的选择会自动设置为当前位置排序后的数据源(我认为)。

要解决此问题,请在排序之前重置您在数据中的位置:

void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1)
            {
                if (dataGridView1.DataSource != null)
                {
                    BindingContext[dataGridView1.DataSource].Position = 0;
                }
            }
        }

或在排序后删除选择(请注意,这也不会改变位置!)

void dataGridView1_Sorted(object sender, EventArgs e)
        {
            if (dataGridView1.SelectedCells.Count > 0)
            {
                dataGridView1.ClearSelection();
            }
        }

编辑: 我发现了一些丑陋的 hack,尽管它需要覆盖 DataGridView 保护的功能。另外,我没有完全测试它,所以以后可能会导致一些奇怪的行为(没有保证)。但它适用于基本设置。首先,调用dataGridView1.ClearSelection(); 在 CellClick 上,如果单击了列标题。然后:

public class DGV:DataGridView
{
        bool isSorted = false;

        public override void Sort(DataGridViewColumn dataGridViewColumn, System.ComponentModel.ListSortDirection direction)
        {
            isSorted = true;
            base.Sort(dataGridViewColumn, direction);
        }
        protected override void OnSorted(EventArgs e)
        {
            base.OnSorted(e);
            isSorted = false;

        }

protected override void SetSelectedCellCore(int columnIndex, int rowIndex, bool selected)
        {
            // here is where cell gets selected so just ignore it when sorting
            if (isSorted)
            {
                return;
            }

            base.SetSelectedCellCore(columnIndex, rowIndex, selected);
}
}
于 2013-06-28T14:12:39.337 回答
0

您是否尝试过将CurrentCell Selected属性设置为False喜欢:

dataGridViewName.CurrentCell.Selected = false;
于 2013-06-28T13:34:36.293 回答