ListBox项目在OwnerDrawFixed模式下不显示

时间:2019-02-22 16:10:21

标签: c# .net winforms ms-access

请,我真的很感谢任何人都可以帮助我解决以下问题。

我有一个Access数据库,我想将其加载到 ListBox 中。
我将列表框DrawMode设置为 OwnerDrawFixed ,但是在运行应用程序时,它显示的是(System.Data.DataRowView)而不是所有数据库记录。

我必须说它在Normal DrawMode下工作正常。

ListBox OwnerDrawFixe Mode Problem Image

这是我的代码:

private void Form1_Load(object sender, EventArgs e)
    {
        ListBox1.DataSource = GetData();
        ListBox1.DisplayMember = "empName";
    }

DataTable dt;

private DataTable GetData()
    {
        dt = new DataTable();
        using (OleDbConnection myConn = new OleDbConnection(ConfigurationManager.ConnectionStrings["database"].ConnectionString))
        {
            using (OleDbCommand myQuery = new OleDbCommand("select empName from empTable", myConn))
            {
                myConn.Open();
                OleDbDataReader myReader = myQuery.ExecuteReader();
                dt.Load(myReader);
            }
        }
        return dt;
    }


private void ListBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        e.DrawBackground();

        bool isItemSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);
        int itemIndex = e.Index;
        if (itemIndex >= 0 && itemIndex < ListBox1.Items.Count)
        {
            Graphics g = e.Graphics;

            SolidBrush backgroundColorBrush = new SolidBrush((isItemSelected) ? Color.FromArgb(255, 64, 64, 64) : Color.FromArgb(0,64,64,64)); 
            g.FillRectangle(backgroundColorBrush, e.Bounds);

            // Set text color
            string itemText = ListBox1.Items[itemIndex].ToString();

            SolidBrush itemTextColorBrush = (isItemSelected) ? new SolidBrush(Color.White) : new SolidBrush(Color.LightGray); 
            g.DrawString(itemText, e.Font, itemTextColorBrush, ListBox1.GetItemRectangle(itemIndex).Location);

            // Clean up
            backgroundColorBrush.Dispose();
            itemTextColorBrush.Dispose();
        }
        e.DrawFocusRectangle();
    }

再次感谢您。

2 个答案:

答案 0 :(得分:2)

我建议这些更改与数据加载和用于填充ListBox的Items集合的方式以及DrawItems方法执行项目绘制的方式有关:

  1. 使用OleDbDataAdapter代替DataTable来填充OleDbDataReader。它使用简单,并会为您打开连接。
  2. 返回一个DataTable,然后将第一列的名称用作ListBox DisplayMember ,因此您无需在此处硬编码用于以下内容的字段名称:提供要显示的信息。您只会在一个地方拥有此参考(不易出错)。
  3. 使用DataTable.DefaultViewDataView对象提供对行的更直接访问,并且可以根据需要进行过滤。 ListBox更喜欢它。
  4. DrawItem方法中删除不必要的部分,并使用GetItemText()方法来检索表示ListControl项目文本的字符串。

我一直在处理DataTable。如果出于任何原因需要此引用,请在使用GetData()方法(此处为Form.Load)时不要废弃它。无论如何,看起来您只是在使用它来检索数据以填充ListBox。


private void Form1_Load(object sender, EventArgs e)
{
    using (DataTable dt = GetData()) {
        listBox1.DisplayMember = dt.Columns[0].ColumnName;
        listBox1.DataSource = dt.DefaultView;
    }
}

private DataTable GetData()
{
    using (OleDbConnection myConn = new OleDbConnection(ConfigurationManager.ConnectionStrings["database"].ConnectionString))
    using (OleDbCommand myQuery = new OleDbCommand("SELECT empName FROM empTable", myConn))
    using (OleDbDataAdapter adapter = new OleDbDataAdapter(myQuery)) {
        var dt = new DataTable();
        adapter.Fill(dt);
        return dt;
    }
}

private void ListBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index < 0) return;
    e.DrawBackground();
    bool isItemSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);
    using (SolidBrush bgBrush = new SolidBrush(isItemSelected ? Color.FromArgb(64, 64, 64) : Color.FromArgb(0, 64, 64, 64)))
    using (SolidBrush itemBrush = isItemSelected ? new SolidBrush(Color.White) : new SolidBrush(Color.LightGray))
    {
        string itemText = listBox1.GetItemText(listBox1.Items[e.Index]);
        e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
        e.Graphics.FillRectangle(bgBrush, e.Bounds);
        e.Graphics.DrawString(itemText, e.Font, itemBrush, e.Bounds);
    }
    e.DrawFocusRectangle();
}

答案 1 :(得分:1)

由于ListBox数据绑定,因此将从DataSource中提取字符串。

因此,当您要所有者绘制列表框时,只需执行以下操作之一即可:

string itemText = ((DataRowView)listBox1.Items[itemIndex]).Row["empName"].ToString();

或者,如Jimi建议的那样,使用GetItemText函数。

请注意,这很难找到,因为它不是ListBox而是ListControl函数。

当然,对字段名称进行硬编码不是一个好主意,但这至少应该使您指向数据。