如何自定义System.Windows.Forms.ListViewItem?

时间:2015-07-30 00:24:59

标签: c# .net winforms listview listviewitem

我正在开发一个Office插件,并想生成这样的东西: screenshot

现在我正在使用ListView,但ListViewItem,即使在Tile模式下,也无法自定义为我想要的。它最多只允许2行文本。

任何人都可以帮助指向我可以使用的正确的Windows窗体控件吗?我应该扩展ListView或ListViewItem吗?任何现有的解决方案?

谢谢,

1 个答案:

答案 0 :(得分:4)

我建议使用ListBox。我将为您重现一个例子。

将ListBox放入表单中。然后你可以在Form的OnLoad事件上编写类似于这个的代码:

    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;
    }

现在,编辑ListBox DrawItem事件,并编写与此类似的代码:

    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);
    }

而且,在跑步时,我们有类似的东西。它与你的例子非常相似,不是吗?

Our example reproduced

如果您想进行更多更改,只需在DrawItem事件中使用绘图即可。希望它有所帮助!