代码之家  ›  专栏  ›  技术社区  ›  Wodzu

将数据正确绑定到组合框并处理其事件

  •  5
  • Wodzu  · 技术社区  · 14 年前

    我在SQL Server中有一个表,如下所示:

    ID Code Name     Surname
    1   MS  Mike     Smith 
    2   JD  John     Doe
    3   UP  Unknown  Person
    

    等等…

    现在,我想将这个表中的数据绑定到组合框中,在组合框中,我已经显示了代码列中的值。

    我是这样装订的:

    SqlDataAdapter sqlAdapter = new SqlDataAdapter("SELECT * FROM dbo.Users ORDER BY Code", MainConnection);
    sqlAdapter.Fill(dsUsers, "Users");
    cbxUsers.DataSource = dsUsers.Tables["Users"];
    cmUsers = (CurrencyManager)cbxUsers.BindingContext[dsUsers.Tables["Users"]];
    cbxUsers.DisplayMember = "Code";
    

    这个代码似乎有效。我可以滚动浏览代码列表。另外,我可以开始手工编写代码,组合框会自动为我完成代码。

    但是,我想在组合框的顶部放置一个标签,以显示当前所选用户代码的名称和姓氏。

    我的思路是这样的:“所以,我需要找到一个事件,它将在组合框中的代码更改后启动,在这种情况下,我将得到当前的数据行…”

    我正在浏览ComboBox的事件,尝试了很多,但都没有成功。

    例如:

    private void cbxUsers_SelectionChangeCommitted(object sender, EventArgs e)
    {
     if (cmUsers != null)
     {
      DataRowView drvCurrentRowView = (DataRowView)cmUsers.Current;
      DataRow drCurrentRow = drvCurrentRowView.Row;
      lblNameSurname.Text = Convert.ToString(drCurrentRow["Name"]) + " " + Convert.ToString(drCurrentRow["Surname"]);
     }
    }
    

    这给了我一个奇怪的结果。首先,当我通过鼠标滚动滚动时,它不会返回我期望获得的行。例如,在JD上,它显示我“Mike Smith”,在MS上,它显示我“John Doe”,在上面,它再次显示我“Mike Smith”! 另一个问题是,当我开始输入组合框并按Enter键时,它不会触发事件。

    但是,当我将数据绑定到lblnamesurname.text时,一切都按预期工作:

    lblNameSurname.DataBindings.Add("Text", dsusers.Tables["Users"], "Name");
    

    这里的问题是我只能绑定一列,而我想要两列。我不想为它使用两个标签(一个显示名称,另一个显示姓氏)。

    那么,我的问题的解决方案是什么?

    另外,我还有一个与组合框中的数据选择相关的问题。现在,当我在组合框中键入某些内容时,它允许我键入列表中不存在的字母。 例如,我开始输入“j”,而不是以“d”结束,所以我会输入“j d”,我在这里输入“jsomeRandomTexthere”。组合框将允许这样做,但列表中不存在此类项。换句话说,我希望组合框防止用户键入不在代码列表中的代码。

    5 回复  |  直到 9 年前
        1
  •  2
  •   SPFiredrake    14 年前

    我自己做了一个测试,我想你可能在寻找的是错误的事件(甚至可能是错误的对象)。

    我刚尝试将事件添加到currencymanager对象(cmusers)的positionChanged处理程序中,它的工作方式与预期完全相同。我唯一的问题是,这是第一次加载,它没有击中位置改变,所以第一个项目从来没有绑定到标签(我相信有一个更容易的解决办法)。 http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingmanagerbase.positionchanged.aspx

    运行了一个小测试,以查看哪个事件首先被激发,并且似乎是在positionChange之前激发的SelectionChangeCommitted事件,这意味着currencyManager尚未更新其内部位置,因此行:

    DataRowView drvCurrentRowView = (DataRowView)cmUsers.Current;
    

    提取错误的数据行。

    忘记第二期了。大多数控件不处理按键,因此应该绑定onkeydown或onkeypress事件以运行所需的任何函数(查找与类型化对象关联的索引[ie.findstring()],并将ComboBox.SelectedIndex属性设置为找到的索引,否则将闪烁警告)。例如:

    if(e.KeyCode == Keys.Enter)
    {
        int indx;
        cmbBox.SelectAll();
        if((indx = FindString(cmbBox.SelectedText)) != -1)
            cmbBox.SelectedIndex = indx;
        else
            // Some warning
    }
    

    编辑 在阅读了你的评论之后,我想出了一个更简单的方法来进行验证。在组合框的“按键”事件中,使用以下代码:

    if(e.KeyChar != (char)Keys.Enter)
    {
        if(cmbBox.FindString(cmbBox.Text + e.KeyChar) == -1)
        {
            e.Handled= true;
        }
    }
    

    不要大惊小怪,不要弄脏了。由于我们仅限于列表中的项目,因此在按Enter键时不需要进行处理,因为它会自动更改所选项目(但是,运行一些验证以确保情况正确,或者只在按Enter键时手动更改SelectedIndex属性不会造成伤害)。 不过,希望这能帮上忙。

        2
  •  0
  •   Scott Chamberlain    14 年前

    对于你的第二个问题,我通常采用的两种方法是 Validating 离开窗体(并禁用“继续”按钮或引发错误消息)或设置前组合框的事件 ComboBox.DropDownStyle ComboBoxStyle.DropDownList

        3
  •  0
  •   Alex Humphrey    14 年前

    尝试以下操作:

    手动创建一个绑定对象,这样您就有了对它的引用。使用绑定对象绑定到组合框的SelectedItem属性。我想这应该能让你得到选定的数据行。将该绑定对象添加到标签的数据绑定集合中。

    处理binding.format事件(或者它可能是parse-can't must member which event applied when binding in which direction),并使用在event args对象中接收的datarow对象来形成一个包含名字和姓氏的适当名称字符串。您需要将EventArgs的其他一些属性设置为该字符串。

    您可能还必须使用绑定类的FormattingEnabled属性-我上次这样做已经有一段时间了,我只是记得这有点棘手。

    有关分析和格式化事件的信息,请参阅文档: http://msdn.microsoft.com/en-us/library/system.windows.forms.binding_events.aspx

        4
  •  0
  •   Peter Mortensen nickfox    10 年前

    好吧,您可以更改SQL,将名称和姓氏作为一列,然后绑定到该列一次。另外,我将把组合和标签放在Ajax更新面板中。

    关于验证:要在客户机上验证,您需要提前在客户机上获取所有可能的值,或者对每个字符进行回发,并使用一个(这可能不是一个好主意-杀死服务器)命中SQL:

    SELECT code FROM TABLE WHERE code LIKE @x + '%' 
    

    自动完成框是否可以接受?看一看 jQuery `例如,自动完成框。

        5
  •  0
  •   Peter Mortensen nickfox    10 年前

    通常,当您更改选择和 把你的注意力转移到外面 如单击外部或按Tab键…

    如果您需要立即触发它,则应通过查找其他事件或调用事件 javascript onchange事件 等。