7

我的winforms技能有点生疏。我正在使用BindingSourcea DataGridView。在我想选择按需要工作的下一个/上一个记录KeyDownDataGridView

Keys.Down如果用户在选择最后一个项目时点击,我想选择第一个,如果他在选择第一个项目时点击,我想选择最后Keys.Up一个。但那时什么也没有发生。

这是代码:

private void  Grid_Keydown(Object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Up)
        previousItem();
    else if (e.KeyCode == Keys.Down)
        nextItem();
}

private void previousItem()
{
    BindingSource bs = null;
    switch (this.Type) // a custom enum
    {
        case AdminType.Channel:  
            bs = channelBindingSource;
            break;
        default:
            break;
    }
    if (bs.Position - 1 < 0)
        bs.MoveLast();
    else
        bs.MovePrevious();
}

private void nextItem()
{
    BindingSource bs = null;
    switch (this.Type)
    {
        case AdminType.Channel:
            bs = channelBindingSource;
            break;
        default:
            break;
    }
    if (bs.Position + 1 >= bs.Count)
        bs.MoveFirst();
    else
        bs.MoveNext();
}

请注意,bs.MoveFirst()/bs.MoveLast()被正确调用但没有任何反应。

编辑DataGridView:有趣的是,当我从按钮(上一个/下一个)而不是's触发它时,它按预期工作OnKeyDown,有什么想法吗?

4

2 回答 2

2

当您上下移动时,网格会自动移动底层绑定源的位置。

如果您希望选择从顶部到按钮,反之亦然 - 您可以处理grid_KeyDown事件并检查它的位置。不幸的是,如果您尝试移动位置,它会被 gridview 的Row_Enter事件覆盖。从而改变绑定源的位置。

如果Grid_Keyup位置已经设​​置,那么您不知道用户是否只是移动到该行,或者他/她是否想离开该行。但是在这里设置bindingSource.Position确实有效 - 并且不会被网格覆盖。

您也可以使用,DataGridViewRow.Selected = true但他不会移动底层绑定源的位置。此外,启用多选的网格也不理想。

丑陋的事实是,您必须使用布尔值(就像您在自己的答案中所做的那样)来控制该行是否应该跳转。:(

但是您不需要从PositionChanged事件中控制它,您只需处理grid_Keydown事件即可:

 private bool _changePost;
    private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
    {
        var view = sender as DataGridView;
        var bs = bindingSource1;

        if (e.KeyData == Keys.Up)
        {
            if (bs.Position == 0 && _changePost)
            {
                _changePost = false;
                bs.MoveLast();
            }
            if (bs.Position == 0 && !_changePost)
                _changePost = true;

        }
        else if (e.KeyData == Keys.Down)
        {
            if (bs.Position == bs.Count - 1 && _changePost)
            {
                bs.MoveFirst();
                _changePost = false;
            }
            if (bs.Position == bs.Count - 1 && !_changePost)
                _changePost = true;
        }
    }

这是我能得到的最干净的。

于 2013-03-11T19:13:55.020 回答
2

感谢 Jens Kloster,我找到了这个解决方法。正如他提到的,DataGridView已经支持移动它的位置BindingSource。因此,如果它具有焦点并且您按向上/向下箭头,则BindingSource's MoveNext/MovePrevious被隐式调用。

我注意到,当我处理KeyUp事件(稍后是KeyDown事件)时,所选项目“跳跃”了两个位置,一个用于编程,一个用于内置移动。

因此,如果按下向上/向下键,我只需要找到一种方法将位置从第一个移动到最后一个,反之亦然。因此,我处理了BindingSource.PositionChanged事件以设置一个 bool 变量,我可以稍后检查:

bool positionChanged = false;
private void Source_PositionChanged(object sender, EventArgs e)
{
    positionChanged = true;
}

private void Grid_KeyUp(Object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Up)
        previousItem();
    else if (e.KeyCode == Keys.Down)
        nextItem();

    positionChanged = false;
}

private void previousItem()
{
    BindingSource bs = null;
    switch (this.Type)
    {
        case AdminType.Channel:
            bs = channelBindingSource;
            break;
        default:
            break;
    }
    if (!positionChanged && bs.Position == 0)
        bs.MoveLast();
    else if (!positionChanged)
        bs.MovePrevious();
}

private void nextItem()
{
    BindingSource bs = null;
    switch (this.Type)
    {
        case AdminType.Channel:
            bs = channelBindingSource;
            break;
        default:
            break;
    }
    if (!positionChanged && bs.Position == bs.Count - 1)
        bs.MoveFirst();
    else if (!positionChanged)
        bs.MoveNext();
}

我仍然愿意寻求更好的解决方案,因为这有点笨拙且容易出错。

于 2013-03-11T14:58:32.093 回答