C# BindingSource MoveFirst/MoveLast不工作

C# BindingSource MoveFirst/MoveLast不工作,c#,winforms,data-binding,bindingsource,C#,Winforms,Data Binding,Bindingsource,我的winforms技能有点生疏了。我正在为DataGridView使用BindingSource。在DataGridView的按键下,我想选择下一个/上一个记录,它可以按需要工作 如果用户按了键,我想选择第一个。选择最后一个项目时向下,如果用户按了键,则选择最后一个。选择第一个项目时向上。但那时什么也没发生 代码如下: private void Grid_Keydown(Object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Up

我的winforms技能有点生疏了。我正在为DataGridView使用BindingSource。在DataGridView的按键下,我想选择下一个/上一个记录,它可以按需要工作

如果用户按了键,我想选择第一个。选择最后一个项目时向下,如果用户按了键,则选择最后一个。选择第一个项目时向上。但那时什么也没发生

代码如下:

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的OnKeyDown按钮触发此按钮时,它会按预期工作,有什么想法吗?

感谢Jens Kloster,我找到了这个解决方法。正如他提到的,DataGridView已经支持移动其BindingSource的位置。因此,如果它有焦点,并且您点击向上/向下箭头,则会隐式调用BindingSource的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();
}

我仍然希望找到更好的解决方案,因为这有点笨拙而且容易出错。

当您上下移动时,网格会自动移动底层bindingsource的位置

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

在Grid_Keyup事件中,位置已经设置,因此您不知道用户是否只是移动到该行,或者他/她是否想要离开该行。但是在这里设置bindingSource.Position实际上是有效的,并且不会被网格覆盖

您也可以使用DataGridViewRow.Selected=true,但his不会移动底层bindingsource的位置。此外,启用“multiselect”也不适用于栅格

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

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


这是我能弄到的最干净的衣服。

你能试试bs.EndEdit;在moveFirst/Last之后?@NDJ:谢谢,但也不起作用。也许网格中的某些内容会覆盖bs位置。尝试使用稍后的事件,如KeyUp@JensKloster:嗯,现在如果我按键,当前项目将跳转两个位置。向上/向下。是什么原因造成的?请尝试注释所有显示的代码,看看是否有效:谢谢你的帮助。很遗憾,没有这个丑陋的变量,就没有方法:
 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;
        }
    }