【问题标题】:How to stop text created by CheckBoxRenderer.DrawCheckBox from layering如何停止由 CheckBoxRenderer.DrawCheckBox 创建的文本分层
【发布时间】:2010-12-04 03:04:12
【问题描述】:

我有以下单元格用于我的数据网格上的自定义列数据类型。

public class DataGridViewReviewerCell : DataGridViewCell
{
    protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle,
                                                TypeConverter valueTypeConverter,
                                                TypeConverter formattedValueTypeConverter,
                                                DataGridViewDataErrorContexts context)
    {
        return Value;
    }

    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
                                  DataGridViewElementStates cellState, object value, object formattedValue,
                                  string errorText, DataGridViewCellStyle cellStyle,
                                  DataGridViewAdvancedBorderStyle advancedBorderStyle,
                                  DataGridViewPaintParts paintParts)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, "", "", errorText,
                 cellStyle, advancedBorderStyle, paintParts);
        var parent = (DataGridViewReviewerColumn) OwningColumn;
        var columnValue = (ReviewerCheckBox) Value;

        CheckBoxRenderer.DrawCheckBox(
            graphics,
            new Point(cellBounds.X + 4, cellBounds.Y + 4),
            new Rectangle(cellBounds.X + 2, cellBounds.Y + 4, cellBounds.Width, cellBounds.Height - (4 * 2)),
            "     " + columnValue.ReviewerEmployeeName,
            parent.InheritedStyle.Font, 
            TextFormatFlags.Left,
            false,
            (columnValue.IsChecked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal));

    }
}

此类按预期工作,但是每次调用 Paint() 时,文本(当前为 " " + columnValue.ReviewerEmployeeName)都会不断分层,创建非常不可读的文本。我似乎找不到任何可以解决此问题的方法。

一段慢代码

这是一段运行非常缓慢的代码。当我将其置于调试模式时,它似乎在无休止地运行。

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            dataGridView1.Rows.Add("STEP A", new ReviewerCheckBox());
            dataGridView1.Rows.Add("STEP B", new ReviewerCheckBox());
        }

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1 || e.ColumnIndex != 1) return;

            var cell = (ReviewerCheckBox) dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
            cell.IsChecked = !cell.IsChecked;
            cell.ReviewerEmployeeName = (cell.IsChecked ? Environment.UserName : String.Empty);

            //MessageBox.Show("Testing");
        }
    }

    public class ReviewerCheckBox
    {
        public string ReviewerEmployeeName { get; set; }
        public bool IsChecked { get; set; }
        public bool IsRequired { get; set; }
    }
}

    public class DataGridViewReviewerColumn : DataGridViewColumn
    {
        public DataGridViewReviewerColumn()
        {
            CellTemplate = new DataGridViewReviewerCell();
            ReadOnly = false;
            SortMode = DataGridViewColumnSortMode.NotSortable;
            Resizable = DataGridViewTriState.False;
        }
    }

【问题讨论】:

    标签: c# winforms .net-3.5 datagridview


    【解决方案1】:

    您应该检查paintParts 参数以确定您应该绘制哪些部分。例如,如果背景需要绘制,DataGridViewPaintParts.Backgound 标志将被设置。

    if (paintParts.HasFlag(DataGridViewPaintParts.Background))
    {
      using (SolidBrush cellBackground =
        new SolidBrush(cellStyle.BackColor))
      {
        graphics.FillRectangle(cellBackground, cellBounds);
      }    
    }
    
    if (paintParts.HasFlag(DataGridViewPaintParts.Border))
    {
      PaintBorder(graphics, clipBounds, cellBounds, cellStyle,
        advancedBorderStyle);
    }
    
    // Paint you cell content here
    

    这是一个稍微完整的例子

    using System;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Windows.Forms.VisualStyles;
    
    namespace HideMainWinForm
    {
      class DataGridViewReviewerCell : DataGridViewCell
      {
        protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
        {
          return value;
        }
    
        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
          if (paintParts.HasFlag(DataGridViewPaintParts.Background))
          {
            using (SolidBrush cellBackground =
              new SolidBrush(cellStyle.BackColor))
            {
              graphics.FillRectangle(cellBackground, cellBounds);
            }
          }
    
          if (paintParts.HasFlag(DataGridViewPaintParts.Border))
          {
            PaintBorder(graphics, clipBounds, cellBounds, cellStyle,
              advancedBorderStyle);
          }
    
          if (value != null)
          {
            CheckBoxRenderer.DrawCheckBox(
              graphics,
              new Point(cellBounds.X + 4, cellBounds.Y + 4),
              new Rectangle(cellBounds.X+24,cellBounds.Y+4, cellBounds.Width-24, cellBounds.Height-4),
              formattedValue.ToString(),
              OwningColumn.InheritedStyle.Font,
              TextFormatFlags.Left,
              false,
              CheckBoxState.CheckedNormal);
          }
        }
      }
    }
    

    两个HasFlag函数调用可以翻译成

    if ((paintParts & DataGridViewPaintParts.Background) == 
        DataGridViewPaintParts.Background)
    {
      ...
    }
    
    if ((paintParts & DataGridViewPaintParts.Border) == 
        DataGridViewPaintParts.Border)
    {
      ...
    }
    

    【讨论】:

    • 感谢您的回复,克里斯。我的 paintParts 参数似乎为空。此外,paintParts 没有 HasFlag 方法。
    • @Mike,HasFlag 自框架 3.5 起是 enum 的成员。 paintParts 不能为空,因为它是不可为空的值类型(枚举)。
    • 由于我使用的是VS2010,我切换到4.0,错误消失了。我将弄清楚如何将其更改为与 3.5 兼容。谢谢。 :)
    • @Mike,MSDN 错误地将 Enum 记录为在 Framework 3.5 中具有 HasFlag 方法。我添加了可用于 Framework 4.0 之前的 Framework 版本的备用标志检查。
    • 关于为什么使用这个确切的代码会导致Paint() 在无限循环中被调用的任何想法?
    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多