ListBox 项目在 OwnerDrawFixed 模式下不显示
Posted
技术标签:
【中文标题】ListBox 项目在 OwnerDrawFixed 模式下不显示【英文标题】:ListBox items do not show in OwnerDrawFixed Mode 【发布时间】:2019-02-22 16:10:21 【问题描述】:拜托,我非常感谢任何人都可以帮助我解决以下问题。
我有一个 Access 数据库,我想将它加载到 ListBox。
我将 ListBox DrawMode
设置为 OwnerDrawFixed
,但是当我运行应用程序时,它显示 (System.Data.DataRowView)
而不是所有数据库记录。
我必须说它在 Normal DrawMode 下运行良好。
这是我的代码:
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();
再次感谢您。
【问题讨论】:
这通常是没有向列表框添加字符串而是某些对象(属于没有好的 ToString 方法的类)的症状。你不应该也设置一个 ValueMember 吗? @TaW,谢谢。我非常努力。但还是想不通。请帮我写代码。 【参考方案1】:我建议对数据加载和用于填充 ListBox 的 Items 集合的方式以及 DrawItems
方法执行项目绘制的方式进行这些更改:
-
使用OleDbDataAdapter 填充
DataTable
而不是OleDbDataReader
。它使用简单,可以为您打开连接。
返回一个DataTable
,然后使用第一个列的名称作为列表框DisplayMember
,因此您不需要硬编码(此处)提供信息的字段名称显示。您只能在一个地方获得此参考资料(不易出错)。
删除DrawItem
方法中不必要的部分,并利用GetItemText() 方法检索表示ListControl
项目文本的字符串。
protected override void OnLoad(EventArgs e)
base.OnLoad(e);
var dt = GetData();
if (dt != null)
listBox1.DisplayMember = dt.Columns[0].ColumnName;
listBox1.DataSource = dt;
private DataTable GetData()
using (var conn = new OleDbConnection(ConfigurationManager.ConnectionStrings["database"].ConnectionString))
using (var cmd = new OleDbCommand("SELECT empName FROM empTable", conn))
conn.Open();
using (var reader = cmd.ExecuteReader())
if (!reader.HasRows) return null;
var dt = new DataTable();
dt.Load(reader);
return dt;
private void ListBox1_DrawItem(object sender, DrawItemEventArgs e)
if (e.Index < 0) return;
var lbx = sender as ListBox;
bool isItemSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);
using (SolidBrush bgBrush = new SolidBrush(isItemSelected ? Color.FromArgb(64, 64, 64) : lbx.BackColor))
using (SolidBrush itemBrush = isItemSelected ? new SolidBrush(lbx.ForeColor) : new SolidBrush(Color.LightGray))
string itemText = lbx.GetItemText(lbx.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();
【讨论】:
【参考方案2】:由于ListBox
是数据绑定,因此从DataSource
中提取字符串。
因此,当您想要所有者绘制列表框时,您需要这样做:
string itemText = ((DataRowView)listBox1.Items[itemIndex]).Row["empName"].ToString();
或者,正如 Jimi 建议的那样,使用 GetItemText
函数。
请注意,这有点难找,因为它不是 ListBox
而是 ListControl
函数..
当然,对字段名称进行硬编码不是一个好主意,但这至少应该将您指向数据。
【讨论】:
以上是关于ListBox 项目在 OwnerDrawFixed 模式下不显示的主要内容,如果未能解决你的问题,请参考以下文章
让 ListBox 中的项目取决于在 ComboBox 中选择了哪个项目
ListBox 的 Scrollviewer 根据项目数可见