我的winforms技能有点生疏。我使用BindingSource
表示DataGridView
。在KeyDown
的{{1}}上,我想选择符合要求的下一个/上一个记录。
如果用户在选择最后一个项目时点击DataGridView
,我想选择第一个,如果在选择第一个项目时点击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()
的{{1}}触发此任何想法时,它会按预期工作吗?< / p>
答案 0 :(得分:2)
感谢Jens Kloster,我找到了这个解决方法。正如他所提到的,DataGridView
已经支持移动它的位置BindingSource
。因此,如果它具有焦点并且您向上/向下箭头,那么BindingSource
的{{1}} / MoveNext
会被隐含地调用。
我注意到,当我处理MovePrevious
事件(稍后是KeyUp
事件)时,所选项目“跳转”了两个位置,一个用于程序设计,一个用于内置移动。
所以我只需要找到一种方法将位置从第一个移动到最后一个,反之亦然,如果按下向上/向下键。因此我处理了KeyDown
事件以设置bool变量,我可以稍后检查:
BindingSource.PositionChanged
我仍然愿意接受更好的解决方案,因为这有点笨拙且容易出错。
答案 1 :(得分:2)
当您上下移动时,网格会自动移动底层绑定源的位置。
如果您希望选择从顶部到按钮,反之亦然 - 您可以处理grid_KeyDown
事件并检查它的位置。不幸的是,如果您尝试移动该位置,它会被gridview的Row_Enter
事件覆盖。从而改变了bindingsource的位置。
在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;
}
}
这就像我能得到的一样干净。