当用户单击另一行中的单元格时,有没有办法保持DataGridView行的选择状态?

3
DataGridView 控件允许您单击行标题并选择行(整行被高亮显示),或使用鼠标单击并拖动以选择多行等方式选择所有行。

无论如何,如果用户决定在 DataGridView 中的某个单元格上单击,则需要保留所选行。因此,如果用户单击所选行中的单元格,则应保留所选行的高亮显示。如果用户单击不同的、未选中的行中的单元格,则应保留所有当前选定的单元格的高亮显示。实际上,除非使用行标题,否则我不希望行选择发生任何变化。

这是一项易于配置的任务,还是需要几天时间进行编程?


好的,我想到了另一种实现我想要的方式。你们不必再回答这个问题了!谢谢大家。 - Isaac Bolinger
最佳实践是发布您自己的解决方案并接受它 - 您可能会在未来帮助到某个人。 - Kirk Broadhurst
与此同时,您最好只是训练您的用户,在他们单击单元格时,实际上他们正在选择一行。他们应该很快学会这一点——这是默认行为。 - Kirk Broadhurst
1
不,它并不是这样的。你必须将其设置为FullRowSelect才能成立。行标题上的小三角形并不意味着该行在所选行的集合中。默认情况下,我认为它被设置为RowHeaderSelect。无论如何,datagridview的默认行为是彻底的垃圾,我已经对其进行了很多改变。 - Isaac Bolinger
无论如何,我还没有解决这个问题... 我只是改变了我的设计,所以我不必解决它 :( - Isaac Bolinger
3个回答

2
我会说这不是一个好主意,从用户的角度来看,这是不需要的行为,你需要教他们只能通过行头选择行(相信我,他们会感到沮丧)。你在某种程度上阻止了用户选择行。
话虽如此,如果你坚持这种设计,你需要自己完成。GridView没有任何内置的行为可以实现这个功能。你可以尝试使用RowChanged事件和CanSelect属性进行一些重写。
此外,还有一个RowHeaderMouseClick事件可以用于从行头选择行。点击此处

不,这不是什么大问题。我的用户基数最多只有4-5人。他们已经习惯了通过点击行标题来删除多行。目前在我的程序中,通过单击单元格选择行没有任何实际用途。我放弃它并不会有任何损失。 - Isaac Bolinger
@IsaacB:啊,你是否已将 DataGridViewSelectionMode 属性设置为 "FullRowSelect"?这会导致单击单个单元格选择整行。如果不是你想要的,请将该属性更改为类似于 "RowHeaderSelect" 的内容。(所有可能值都在此处列出。) - Cody Gray
@IsaacB 好的,那么我已经提到了如何通过利用RowHeaderMouseClick事件来实现这一点..祝你好运 :) - Shekhar_Pro
@Cody Gray,“RowHeaderSelect”模式仍会在单击单元格时选择该单元格。OP仍需要覆盖此行为。 - Shekhar_Pro
@Shekhar:不,它不会。点击其中一个单元格只会选择该单元格,但不会选择整行。不清楚这是否实际上解决了问题,但这可能是他最后一条评论的答案。 - Cody Gray
不,选择模式对我帮助不大。真正的问题是用户如何与网格视图中的按钮、复选框和其他元素进行交互,而不会取消已选择的行。这就是为什么我希望只能使用行标题来选择行。将其设置为rowheaderselect听起来像是解决方案,但单击单元格会取消所选行。 - Isaac Bolinger

2
配置不容易。使用DataGridView控件几天后,你会发现除非开发人员决定将其公开为属性,否则它的任何部分都不容易配置。而且只有最简单的东西以这种方式公开,所以不要浪费太多时间寻找。
当然,这是可能的。我已经花费了太多的时间来子类化DataGridView控件并覆盖我认为愚蠢的内置行为。但我真的不建议任何人这样做。
更重要的是,你应该认真重新考虑是否甚至想要进行这种特定的更改。如果软件开始这样做,我会一无所知。我会立即怀疑我的Shift键或鼠标按钮被卡住了,并试图将它们解决。下一步将是重新启动我的计算机。总体而言,用户体验并不是很好。控件之所以不会这样行动,是有原因的。请仔细考虑单元格高亮在语义上实际意味着什么——通常,暗示是你可以一次更改或删除所有选定的单元格。如果你的实现不是这样工作的,你可能根本不应该这样做。

太晚了。我已经对DataGridView进行了子类化,并且已经修复了许多令人讨厌的行为,并添加了一些对我有用的新行为。我已经弄清楚如何在其中添加自己的控件...现在我无法摆脱这该死的DGV了。而且,我越深入地研究它的工作原理,似乎越难找到关于它的帮助。唉,算了。 - Isaac Bolinger
@IsaacB:是的,那是因为DGV是一种没有人想使用的混蛋控件。每个做任何非平凡事情的人最终都会重新实现该死的东西,但肯定不想花时间帮助其他人做同样的事情。痛苦的回忆,我想。如果你想继续下去,你别无选择,只能自己掌握所有选择行为。防止控件将单元格、行或列添加到选定项属性中,并在OnRowHeaderMouseClick方法的重写中自己添加它们。 - Cody Gray
"我花了太多时间在子类化DataGridView控件上" 我明白你的感受! - Dave Cousineau

1
我使用 DataGridView 子类化来绕过这个问题,抱歉。
这可以干净地完成,只需在取消选择的内部机制之前和之后添加几个委托:
class SimpleDataGridView : DataGridView {

    public Action<DataGridViewCellMouseEventArgs> BeforeCellMouseDown;
    public Action<DataGridViewCellMouseEventArgs> AfterCellMouseDown;

    protected override void OnCellMouseDown(DataGridViewCellMouseEventArgs e) {
        if(BeforeCellMouseDown != null)
            BeforeCellMouseDown(e);

        base.OnCellMouseDown(e);

        if(AfterCellMouseDown != null)
            AfterCellMouseDown(e);
    }
}

然后,在您的构造函数中可以这样使用它。将“yourCondition”替换为您想确定是否需要保留选择的方式。

IEnumerable<DataGridViewRow> sel = null;

dataGridView1.BeforeCellMouseDown = 
    e => {
        if (yourCondition)
            sel = dataGridView1.SelectedRows.OfType<DataGridViewRow>();
        else
            sel = null;
    };

dataGridView1.AfterCellMouseDown = 
    e => {
        if(sel != null) {
            foreach(var row in sel)
                row.Selected = true;
        }
    };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接