Please, I really appreciate that anyone can help me with the following problem.
I have an Access database which I want to load it into the ListBox.
I set the ListBox DrawMode
to OwnerDrawFixed
, but when I run the application it shows (System.Data.DataRowView)
instead of all the database records.
I must say that it works fine in Normal DrawMode.
Here is my code:
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();
}
Thank you again.
I suggest these changes in relation to the way the data is loaded and used to fill the Items collection of a ListBox and the way the DrawItems
method performs the painting of the items:
DataTable
instead of a OleDbDataReader
. It's simple to use and it takes care of opening the connection for you.DataTable
, then use the first Column's name as the ListBox DisplayMember
, so you don't need to hardcode (here) the name of the Field that provides the information to show. You'll have this reference in one place only (less error prone).DrawItem
method and make use of the GetItemText() method to retrieve the string that represents the ListControl
item text.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 (var bgBrush = new SolidBrush(isItemSelected ? Color.FromArgb(64, 64, 64) : lbx.BackColor))
using (var 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();
}