Reputation: 1132
I am developing an Office plugin and would like to produce something like this:
Right now I am using ListView, but the ListViewItem, even in Tile mode, is not customizable to be what I want. It only allows up to 2 lines of text max.
Anyone can help pointing to the right Windows Forms control that I can use? Should I extend the ListView or ListViewItem? Any existing solution?
Thanks,
Upvotes: 2
Views: 3069
Reputation: 622
I recommend using the ListBox instead. I will reproduce an example for you.
Put a ListBox into your form. Then you can write a code similar to this one on the Form's OnLoad event:
private void Form1_Load(object sender, EventArgs e)
{
// This will change the ListBox behaviour, so you can customize the drawing of each item on the list.
// The fixed mode makes every item on the list to have a fixed size. If you want each item having
// a different size, you can use DrawMode.OwnerDrawVariable.
listBox1.DrawMode = DrawMode.OwnerDrawFixed;
// Here we define the height of each item on your list.
listBox1.ItemHeight = 40;
// Here i will just make an example data source, to emulate the control you are trying to reproduce.
var dataSet = new List<Tuple<string, string>>();
dataSet.Add(new Tuple<string, string>("5:30 PM - 6:00 PM", "11 avaliable rooms"));
dataSet.Add(new Tuple<string, string>("6:00 PM - 6:30 PM", "12 available rooms"));
listBox1.DataSource = dataSet;
}
Now, edit your ListBox DrawItem event, and write a code similar to this one:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
// This variable will hold the color of the bottom text - the one saying the count of
// the avaliable rooms in your example.
Brush roomsBrush;
// Here we override the DrawItemEventArgs to change the color of the selected
// item background to one of our preference.
// I changed to SystemColors.Control, to be more like the list you are trying to reproduce.
// Also, as I see in your example, the font of the room text part is black colored when selected, and gray
// colored when not selected. So, we are going to reproduce it as well, by setting the correct color
// on our variable defined above.
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e = new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds,
e.Index, e.State ^ DrawItemState.Selected, e.ForeColor, SystemColors.Control);
roomsBrush = Brushes.Black;
}
else
{
roomsBrush = Brushes.Gray;
}
// Looking more at your example, i noticed a gray line at the bottom of each item.
// Lets reproduce that, too.
var linePen = new Pen(SystemBrushes.Control);
var lineStartPoint = new Point(e.Bounds.Left, e.Bounds.Height + e.Bounds.Top);
var lineEndPoint = new Point(e.Bounds.Width, e.Bounds.Height + e.Bounds.Top);
e.Graphics.DrawLine(linePen, lineStartPoint, lineEndPoint);
// Command the event to draw the appropriate background of the item.
e.DrawBackground();
// Here you get the data item associated with the current item being drawed.
var dataItem = listBox1.Items[e.Index] as Tuple<string, string>;
// Here we will format the font of the part corresponding to the Time text of your list item.
// You can change to wathever you want - i defined it as a bold font.
var timeFont = new Font("Microsoft Sans Serif", 8.25f, FontStyle.Bold);
// Here you draw the time text on the top of the list item, using the format you defined.
e.Graphics.DrawString(dataItem.Item1, timeFont, Brushes.Black, e.Bounds.Left + 3, e.Bounds.Top + 5);
// Now we draw the avaliable rooms part. First we define our font.
var roomsFont = new Font("Microsoft Sans Serif", 8.25f, FontStyle.Regular);
// And, finally, we draw that text.
e.Graphics.DrawString(dataItem.Item2, roomsFont, roomsBrush, e.Bounds.Left + 3, e.Bounds.Top + 18);
}
And, when running, we have something like that. It is very similar to your example, isn't?
If you want to make more changes, you just need to play with the drawings on the DrawItem event. Hope it helps!
Upvotes: 8