zoukankan      html  css  js  c++  java
  • WinForm下ComboBox获取绑定对象集的SelectedValue补充

    在上文《WinForm下ComboBox设定SelectedValue总》中,我列举了出现不能正常获取SlectedValue的一些方法。原文写得比较乱,引起读者的理解分歧,在此表示歉意。现将自己的思路重新整理一下。

    注意:本文只限定绑定对象集,而不涉及绑定DataSet或DataTable的情况

    (如果绑定DataSet时出现SelectedValue为System.Data.DataRowView的错误,或者在取SelectedVlaue的值转换时出现"不能将对象转换为字符串",请参看这里:Combobox出现System.Data.DataRowView的原因,以及指定ValueMember的时机问题http://blog.csdn.net/lubiaopan/archive/2010/09/30/5915774.aspx)

    一、准备工作:
    为了方便起见,我们暂时将公用方法和变量简化一下:

    一个Area类:

    代码
    #region Area
    public class Area
    {
    private string m_Area_ID;
    public string Area_ID
    {
    get { return m_Area_ID; }
    set { m_Area_ID = value; }
    }

    private string m_Area_Name;
    public string Area_Name
    {
    get { return m_Area_Name; }
    set { m_Area_Name = value; }
    }

    private double m_Area_Order;
    public double Area_Order
    {
    get { return m_Area_Order; }
    set { m_Area_Order = value; }
    }
    }
    #endregion

    [Serializable]
    public class AreaLists : List<Area>
    {
    private int _maxItems = 0;
    public int MaxItems { get { return this._maxItems; } set { this._maxItems = value; } }
    }

    一个WinForm,命名为frmMain

    一个ComboBox,名为cbList

    两个button,名为btnSetComboboxbtnGetSelectedValu

    一个Label,名为lbResult,初始值为Unknown

    定义公共变量:

    AreaLists ac;
    public AreaLists GetTestArea()
    {
    AreaLists al
    = new AreaLists();
    for (int i = 1; i < 11; i++)
    {
    Area a
    = new Area();
    a.Area_ID
    = i.ToString();
    a.Area_Name
    = "" + i.ToString() + "";
    al.Add(a);
    }
    return al;
    }

    几个用到的方法:

    方法一:SetValueByValue(通过ValueMember设置)

    private void SetValueByValue()
    {
    Area a
    = new Area();
    a.Area_ID
    = "8";
    a.Area_Name
    = "第8名";

    cbList.SelectedValue
    = a.Area_ID;
    lbResult.Text
    = cbList.SelectedValue.GetType().ToString() + ":" + cbList.SelectedValue.ToString();
    }

    方法二:SetValueByItem(通过SelectedItem设置)

    private void SetValueByItem()
    {
    Area a
    = new Area();
    a.Area_ID
    = "8";
    a.Area_Name
    = "第8名";

    cbList.SelectedItem
    = ac.FindAll(delegate(Area ar) { return ar.Area_ID == a.Area_ID; })[0];
    lbResult.Text
    = cbList.SelectedItem.GetType().ToString() + ":" + cbList.SelectedValue.ToString();
    }

    方法三:SetValueByText(通过FindString查找DisplayMember设置)

    private void SetValueByText()
    {
    Area a
    = new Area();
    a.Area_ID
    = "8";
    a.Area_Name
    = "第8名";

    cbList.SelectedIndex
    = cbList.FindString(a.Area_Name);
    lbResult.Text
    = cbList.SelectedValue.GetType().ToString() + ":" + cbList.SelectedValue.ToString();
    }

    获取SelectedValue的值:

    private void GetValueByValue()
    {
    lbResult.Text
    = cbList.SelectedValue.GetType().ToString() + ":" + cbList.SelectedValue.ToString();
    }

    如下图:
    邀月工作室

    frmMain的Page_Load事件:

    private void frmMain_Load(object sender, EventArgs e)
    {
    ac
    = GetTestArea();

    cbList.DataSource
    = ac;
    cbList.ValueMember
    = "Area_ID";
    cbList.DisplayMember
    = "Area_Name";

    }

    btnSetCombobox的Click事件:

    private void btnSetCombobox_Click(object sender, EventArgs e)
    {
    //使用方法一:
    SetValueByValue();

    //使用方法二
    //SetValueByItem();

    //使用方法三
    //SetValueByText();
    }
    btnGetSelectedValue的Click事件:

    private void btnGetSelectedValue_Click(object sender, EventArgs e)
    {
    GetValueByValue();
    }
    cbList的SelectedIndexChangedSelectedValueChanged事件:
    private void cbList_SelectedIndexChanged(object sender, EventArgs e)
    {
    // GetValueByValue();
    int test = 0;
    }

    private void cbList_SelectedValueChanged(object sender, EventArgs e)
    {
    //GetValueByValue();
    int test = 0;
    }

    二、测试结果(不考虑绑定结果集为空时的情况)

    使用方法

    1、未设置ComboBox的SelectedIndexChanged事件和SelectedValueChanged事件时SelectedValue类型及值

    Page_Load时

    设置SelectedValue

    读取SelectedValue

    SetValueByValue

    Null

    所选Area_ID对应的字符串

    所选 Area_ID对应的字符串

    SetValueByItem

    Null

    Area

    所选 Area_ID对应的字符串

    SetValueByText

    Null

    所选 Area_ID对应的字符串

    所选 Area_ID对应的字符串

    使用方法

    2、仅设置ComboBox的SelectedIndexChanged事件SelectedValue类型及值

    Page_Load时

    设置SelectedValue

    读取SelectedValue

    SetValueByValue

     第一个 Area_ID对应的字符串

    所选 Area_ID对应的字符串

    所选  Area_ID对应的字符串

    SetValueByItem

     第一个 Area_ID对应的字符串

     Area

     所选 Area_ID对应的字符串

    SetValueByText

     第一个 Area_ID对应的字符串

     所选 Area_ID对应的字符串

    所选  Area_ID对应的字符串

    使用方法

    3、仅设置ComboBox的SelectedValueChanged事件时SelectedValue类型及值

    Page_Load时

    设置SelectedValue

    读取SelectedValue

    SetValueByValue

     第一个 Area_ID对应的字符串

    所选 Area_ID对应的字符串

    所选  Area_ID对应的字符串

    SetValueByItem

    第一个 Area_ID对应的字符串

     Area

     所选A_ID对应的字符串

    SetValueByText

    第一个 Area_ID对应的字符串

     所选 Area_ID对应的字符串

     所选A_ID对应的字符串

    使用方法

    4、同时设置ComboBox的SelectedIndexChanged事件和SelectedValueChanged事件时SelectedValue类型及值

    Page_Load时

    设置SelectedValue

    读取SelectedValue

    SetValueByValue

    第一个 Area_ID对应的字符串

    所选 Area_ID对应的字符串

    所选  Area_ID对应的字符串

    SetValueByItem

     第一个 Area_ID对应的字符串

     Area

     所选 Area_ID对应的字符串

    SetValueByText

    第一个 Area_ID对应的字符串

     所选 Area_ID对应的字符串

    所选  Area_ID对应的字符串

     

    三、结论(不考虑绑定结果集为空时的情况)
     

    本次测试中还发现几个结论:

    1、当ComboBox中无论是否设置SelectedIndexChanged事件和SelectedValueChanged事件,如果没有设置SelectedValue值或设置的值超过ValueMember的范围(即赋错值),则此时SelectedValue为第一个对象对应的 Area_ID值,所以,如果出现没有正确获取到想要的值,请检查是否设置或有没有赋了一个不存在于ValueMember集合的值。


    2、最好设置ComboBox中的SelectedIndexChanged事件和SelectedValueChanged事件,并在事件中获取SelectedValue值。

    有人会担心事件会不会触发?经测试,如果这两个事件同时设置,顺序为:

    cbList.DataSource = ac;//这里会触发SelectedValueChanged事件和 SelectedIndexChanged事件次。
    cbList.ValueMember = "Area_ID";这里会触发SelectedValueChanged事件和 SelectedIndexChanged事件,还有一次SelectedValueChanged事件
    cbList.DisplayMember = "Area_Name";这里会触发SelectedValueChanged事件和 SelectedIndexChanged事件次。

    换句话说,设定两个事件任意一个即可,我建议用SelectedValueChanged事件 

    3、设置正确的绑定顺序。有人指出正确的顺序为: 

      cbList.ValueMember = "Area_ID";//这里会触发SelectedValueChanged事件

    cbList.DisplayMember = "Area_Name";//这里不会触发任何事件

    cbList.DataSource = ac;//这里会触发SelectedValueChanged事件和 SelectedIndexChanged事件次。

    在本次测试中发现顺序其实对结果并没有影响,但是如果将ValueMembe在设置DataSource之前设置,触发事件大大减少!

    所以建议DataSource设置前先设定ValueMember和DisplayMember

    4、如果设置错误的DisplayMember名称,(如本文中" Area_Name"误设为“ Area_Names”)则取ValueMember作为DisplayMember,如果ValueMember的名称也设置错误,(如本文中" Area_ID"误设为“ Area_IDs”)则获取SelectedValue时出错!

    5、回到本文开头,如果绑定的不是对象集,而是DataSet或DataTable,则未设定SelectedValue时,取得的是一个DataRowView而不是null,请注意。

      

  • 相关阅读:
    关于devDependencies和dependencies报错提示及区别 --save 和--save-dev 的区别
    git 创建分支并提交到远程
    静态类中,静态方法和静态变量的执行顺序按出现执行
    Java和C#语法对比
    大数据时遇到的问题
    Javascript技巧笔记
    Javascript特性笔记
    Javascript 之《函数传参到底是值传递还是引用传递》
    Javascript之《创建对象》
    IE之诡异行为
  • 原文地址:https://www.cnblogs.com/downmoon/p/1943018.html
Copyright © 2011-2022 走看看