winform ListView應用之分組、重繪圖標、網格線 (c# .net winform)


最近在winform應用中需要用到可分組的數據列表功能,DataGridView默認沒有提供分組的功能,而OutlookGrid(http://www.codeproject.com/KB/grid/OutlookGrid.aspx)用起來又是相當的麻煩,最后發現了ObjectListView(objectlistview.sourceforge.net),功能相當的強大,強大到我不需要那么多的功能,額~~所以決定參照它的實現,對ListView做一個簡單的擴展(注:本文僅針對ListView的View屬性為Details)。

 

首先為ListView添加好列: 

listViewEx1.Columns.AddRange( new  ColumnHeader[] { new ColumnHeader("列1"), new ColumnHeader("列2"), new ColumnHeader("列3") });

 

分組

這是ListView自帶的功能,用起來也很簡單,只需要把ShowGroups設置為true(默認為true),再為ListView添加ListViewGroup,並為ListViewItem設置Group即可,代碼如下:

ListViewGroup g = new  ListViewGroup("分組");
listViewEx1.Groups.Add(g);
ListViewItem item = new  ListViewItem("數據項", g);
listViewEx1.Items.Add(item);

接下來的重繪方法,就需要通過繼承ListView並重寫OnDrawSubItem(DrawListViewSubItemEventArgs e)方法來實現,在重寫此方法之前,必須設置ListView的OwnerDraw屬性為true,用於啟用重繪。

 

給ListViewSubItem設置圖標

ListView默認可以設置ImageIndex來顯示圖標,但是只能設置在每個ListViewItem上,即每一行數據只能有一個圖標,若要每個ListViewSubItem都能設置圖標,則需要通過重寫OnDrawSubItem(DrawListViewSubItemEventArgs e)方法來實現,關鍵代碼為:

Graphics g = e.Graphics;
Rectangle r = e.Bounds;
Rectangle imageBounds = new  Rectangle(r.Location, image.Size);//image為具體的圖標文件
g.DrawImage(image, imageBounds); //通過DrawImage方法繪制圖標

對這種方法簡單的改造,可以為每一列設置單獨的圖標。

 

網格線

ListView在設置了分組的情況下,GridLines屬性就無效了,所以如果需要顯示網格線,也需要通過重寫OnDrawSubItem(DrawListViewSubItemEventArgs e)方法來實現,關鍵代碼為:

Graphics g = e.Graphics;
Rectangle r = e.Bounds;
using  (Pen pen = new Pen(Color.Gray))
{
     g.DrawRectangle(pen, r.X, r.Y, r.Width, r.Height + 1); //高度加1使橫向線條重疊
}

以上代碼畫了灰色的網格線,也可以簡單改造以實現自定義的網絡線顏色。

 

選中的背景

在重寫OnDrawSubItem(DrawListViewSubItemEventArgs e)方法之后,選中ListView的行,默認的背景色不會出現,所以還得把選中狀態的背景色顯示出來,關鍵代碼為:

     if  ((e.ItemState & ListViewItemStates.Selected)
== ListViewItemStates.Selected)
     {
         using  (SolidBrush brush = new SolidBrush(Color.Blue))
         {
             g.FillRectangle(brush, r);
         }
     }

以上代碼為選中的列繪制了藍色的背景,同樣也可以擴展以上代碼來實現自定義背景色。

 

呈現原始文本

在重寫OnDrawSubItem(DrawListViewSubItemEventArgs e)之后,原來的文本內容同樣也會像背景一樣丟失了,所以需要把原來的文本重新繪制出來,關鍵代碼如下:

Graphics g = e.Graphics;
Rectangle r = e.Bounds;
TextRenderer.DrawText(
     g,
     e.SubItem.Text,
     e.SubItem.Font,
     r,
     e.SubItem.ForeColor,
     TextFormatFlags.Left);

 

其他

1、自動調整列大小:調用AutoResizeColumns方法,listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent) 
2、隱藏列頭:設置HeaderStyle屬性,listView1.HeaderStyle = ColumnHeaderStyle.None 
3、選擇整行:設置FullRowSelect為true 
4、行雙擊事件:綁定ListView的MouseDoubleClick事件,代碼如下:

void  listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
     ListViewHitTestInfo info = listView1.HitTest(e.Location);
     if  (info != null && info.Item != null)
     {
         //...
     }
}

 

完整的代碼

public  class ListViewEx : ListView
{
     public  ListViewEx() :
         base ()
     {
         this .OwnerDraw = true ; //用於啟用重繪
     }
 
     /// <summary>
     /// 圖標
     /// </summary>
     public  Image Icon { get; set; }
 
     /// <summary>
     /// 重繪圖標
     /// </summary>
     public  bool IsDrawIcon { get; set; }
 
     /// <summary>
     /// 重繪網格線
     /// </summary>
     public  bool IsDrawGridLines { get; set; }
 
     /// <summary>
     /// 重繪圖標列
     /// </summary>
     /// <param name="e"></param>
     protected  override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
     {
         if  (View != View.Details ||
             e.ItemIndex == -1)
         {
             e.DrawDefault = true ;
             return ;
         }
 
         Rectangle r = e.Bounds;
         Graphics g = e.Graphics;
 
         DrawSelectedBackground(e, g, r);
 
         int  paddingLeft = 0;
         if  (IsDrawIcon)
         {
             paddingLeft = this .DrawIcon(g, r, this .Icon, e.Item.BackColor).Width;
         }
 
         if  (IsDrawGridLines)
         {
             using  (Pen pen = new Pen(Color.Gray))
             {
                 g.DrawRectangle(pen, r.X, r.Y, r.Width, r.Height + 1); //高度加1使橫向線條重疊
             }
         }
 
         if  (!string.IsNullOrEmpty(e.SubItem.Text))
         {
             this .DrawText(e, g, r, paddingLeft);
         }
     }
 
     /// <summary>
     /// 重繪選中時背景
     /// </summary>
     private  void DrawSelectedBackground(DrawListViewSubItemEventArgs e, Graphics g, Rectangle r)
     {
         if  ((e.ItemState & ListViewItemStates.Selected)
== ListViewItemStates.Selected)
         {
             using  (SolidBrush brush = new SolidBrush(Color.Blue))
             {
                 g.FillRectangle(brush, r);
             }
         }
     }
 
     /// <summary>
     /// 重繪圖標
     /// </summary>
     private  Size DrawIcon(Graphics g, Rectangle r, Image image, Color backColor)
     {
         Rectangle imageBounds = new  Rectangle(r.Location, image.Size);
         if  (image.Height > r.Height)
         {
             float  scaleRatio = (float)r.Height / (float)image.Height;
             imageBounds.Width = ( int )(( float )Icon.Width * scaleRatio);
             imageBounds.Height = r.Height - 1;
         }
         //使圖標不會緊貼着每一列的左上角
         imageBounds.X += 1;
         imageBounds.Y += 1;
 
         g.DrawImage(image, imageBounds);
         return  imageBounds.Size;
     }
 
     /// <summary>
     /// 重繪文本
     /// </summary>
     private  void DrawText(DrawListViewSubItemEventArgs e, Graphics g, Rectangle r, int paddingLeft)
     {
         TextFormatFlags flags = GetFormatFlags(e.Header.TextAlign);
 
         r.X += 1 + paddingLeft; //重繪圖標時,文本右移
         TextRenderer.DrawText(
             g,
             e.SubItem.Text,
             e.SubItem.Font,
             r,
             e.SubItem.ForeColor,
             flags);
     }
 
     /// <summary>
     /// 獲取文本對齊
     /// </summary>
     private  TextFormatFlags GetFormatFlags(
         HorizontalAlignment align)
     {
         TextFormatFlags flags =
                 TextFormatFlags.EndEllipsis |
                 TextFormatFlags.VerticalCenter;
 
         switch  (align)
         {
             case  HorizontalAlignment.Center:
                 flags |= TextFormatFlags.HorizontalCenter;
                 break ;
             case  HorizontalAlignment.Right:
                 flags |= TextFormatFlags.Right;
                 break ;
             case  HorizontalAlignment.Left:
                 flags |= TextFormatFlags.Left;
                 break ;
         }
 
         return  flags;
     }
}

相關的演示代碼:

public  Form1()
{
     InitializeComponent();
 
     ListViewEx listViewEx1 = new  ListViewEx();
     listViewEx1.Icon = Resources.application;
     listViewEx1.IsDrawGridLines = true ;
     listViewEx1.IsDrawIcon = true ;
     listViewEx1.Location = new  Point(0, 0);
     listViewEx1.Name = "listViewEx1" ;
     listViewEx1.Size = new  Size(284, 265);
     listViewEx1.Dock = DockStyle.Fill;
     listViewEx1.FullRowSelect = true ;
     listViewEx1.UseCompatibleStateImageBehavior = false ;
     listViewEx1.View = View.Details;
     listViewEx1.HeaderStyle = ColumnHeaderStyle.None;
     listViewEx1.Columns.AddRange( new  ColumnHeader[] { new ColumnHeader(), new ColumnHeader(), new ColumnHeader() });
 
     for  (int i = 1; i <= 3; i++)
     {
         ListViewGroup g = new  ListViewGroup("分組" + i.ToString());
         listViewEx1.Groups.Add(g);
         for  (int j = 1; j <= 5; j++)
         {
             ListViewItem item = new  ListViewItem(j.ToString(), g);
             item.SubItems.Add((i + j).ToString());
             item.SubItems.Add((i * j).ToString());
             listViewEx1.Items.Add(item);
         }
     }
     this .Controls.Add(listViewEx1);
}

 

DEMO下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM