设想一下这样的一个场景,一个用户在他/她的网格内有一些数据,希望在某一个单元格展示某些数据的状态或进度条。

比如,需要显示一些被拷贝到内存或是类似于windows媒体播放器的用户界面的音轨录音的状态,而被拷贝的这些歌曲的当前状态通过进度条来显示。

 

这个时候,可以使用WinForms 的ComponentOne C1TrueDBGrid,用C1TrueDBGrid的OwnerDrawCell事件实现复杂单元格的用户自定义。OwnerDrawCell事件被用来定制每一个单元格呈现的方式或是彻底重载画面。在本博客中,用C1TrueDBGrid实现该场景。

加载数据
加载数据集到音轨录音表,并用C1TrueDBGrid构建它。

DataTable dt;
private void Form1_Load(object sender, System.EventArgs e)
{
    // load data from resource
    DataSet ds = GetDataSet("tracks.xsd");
 
    // configure grid
    this.c1TrueDBGrid1.MultiSelect = MultiSelectEnum.None;
    this.c1TrueDBGrid1.MarqueeStyle = MarqueeEnum.NoMarquee;
    this.c1TrueDBGrid1.AllowUpdate = false;
            
    // bind grid
    dt = ds.Tables[0];
    this.c1TrueDBGrid1.DataSource = dt;
    this.c1TrueDBGrid1.Columns["Status"].DataWidth = 160;
    this.c1TrueDBGrid1.Splits[0].DisplayColumns["Status"].Width = 160;
    this.c1TrueDBGrid1.Splits[0].DisplayColumns["Status"].OwnerDraw = true;
          
    // create gdi objects
    Color color = Color.HotPink;
    _pen = new Pen(color, 1);
    _bmp = new Bitmap(100, 20);
    Rectangle rc = Rectangle.Empty;
    rc.Size = _bmp.Size;
    using (Graphics g = Graphics.FromImage(_bmp))
using (Brush b = new LinearGradientBrush(rc, Color.Transparent, 
                                     color, LinearGradientMode.Horizontal))
    {
        g.FillRectangle(b, rc);
    }
 
    // start copying all songs right away
    foreach (DataRow dr in ds.Tables[0].Rows)
        _songs[dr] = DateTime.Now;
 
}

 

在单元格中显示进度条

通过处理C1TrueDBGrid的OwnerDrawCell事件把进度条显示在网格单元中。

private void c1TrueDBGrid1_OwnerDrawCell(object sender, 
                                  C1.Win.C1TrueDBGrid.OwnerDrawCellEventArgs e)
{
    // Showing Progress Bar in Column 'Status'
if (this.c1TrueDBGrid1.Splits[0].DisplayColumns[e.Col].Name == "Status"
                                                               && e.Row >= 0)
    {
        DataRow dr = dt.Rows[e.Row];
        if (dr == null)
            return;
        // see if we're copying the song
        if (!_songs.ContainsKey(dr))
            return;
 
        // calculate how much is done
        DateTime start = (DateTime)_songs[dr];
        TimeSpan elapsed = DateTime.Now - start;
        TimeSpan length = (TimeSpan)dr["Length"];
        int pct = (length.TotalSeconds > 0)
            ? (int)(elapsed.TotalSeconds / length.TotalSeconds * 100f * 20f)
            : 100;
 
        // song is done? remove from list
        if (pct >= 100)
        {
            _songs.Remove(dr);
            dr["Status"] = "Copied";
            return;
        }
 
        // draw background
        e.Style = this.c1TrueDBGrid1.Styles["HighlightRow"];
        e.DrawCellFlags = C1.Win.C1TrueDBGrid.Styles.DrawCellFlags.All;
 
        // progress bar outline
        Rectangle rc = e.CellRect;
        rc.Width--;
        rc.Height--;
        e.Graphics.DrawRectangle(_pen, rc);
 
        // fill progress bar
        rc = e.CellRect;
        rc.Inflate(-2, -2);
        rc.Width = rc.Width * pct / 100;
        e.Graphics.DrawImage(_bmp, rc);
                 
        // draw text
        // Create string to draw.
        String drawString = string.Format("Copying ({0}% done)", pct);
        // Create font and brush.
        Font drawFont = new Font("Arial", 8);
        SolidBrush drawBrush = new SolidBrush(Color.Black);
                
        // Draw string to screen.
        e.Graphics.DrawString(drawString, drawFont, drawBrush,
                                                  e.CellRect.X,e.CellRect.Y);
        e.DrawCellFlags = C1.Win.C1TrueDBGrid.Styles.DrawCellFlags.All;
        e.Handled = true;
    }
            
}

 

 源代码如下:

OwnerDrawCell_CS.zip (16.47 kb)

OwnerDrawCell_VB.zip (25.89 kb)