BindingSource MoveFirst/MoveLast doesn't work
本文关键字:work doesn MoveFirst MoveLast BindingSource | 更新日期: 2023-09-27 18:03:23
我的winforms技能有点生疏了。我用BindingSource
代替DataGridView
。在DataGridView
的KeyDown
上,我想选择按需要工作的下一个/上一个记录。
如果用户在选择最后一项时点击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
的OnKeyDown
触发此时,它按预期工作,有什么想法吗?
当你上下移动时,网格会自动移动底层绑定源的位置。
如果你想选择从顶部到按钮,反之亦然-你可以处理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;
}
}
这是我能弄到的最干净的了
多亏了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();
}
我仍然对更好的解决方案持开放态度,因为这有点笨拙和容易出错。