【问题标题】:Display and edit int column from datatable as hours and minutes in datagridview在 datagridview 中将数据表中的 int 列显示和编辑为小时和分钟
【发布时间】:2015-01-26 17:58:15
【问题描述】:

我有一个数据库,其中的字段以分钟为单位表示时间。但是在我的 datagridview 中,我不想将时间显示为 hh:mm。例如。 130 分钟应显示为 02:10,编辑时带有蒙版文本框。我创建了一个 DataGridView 并将一个名为 MaskedTextboxMinutes 的自定义列类放在时间列中,并创建了一个用于处理编辑的自定义控件。我只在编辑单元格时显示文本框,在不编辑时(我不希望在不编辑单元格时显示文本框)。当不编辑原始 int 字段值(例如 130)时,会显示分钟。创建 MaskedTextboxMinutes 以将分钟作为输入和输出,但显示为 hh:mm。问题是,我在哪里放置一些代码来覆盖列的显示方式?我想避免覆盖 onpaint。

这些是我的 MaskedTextBoxMinutes 和 DataGridView 单元格、列和控件的类:

时间类:

class Time
{
    public int Hours { get; set; }
    public int Minutes { get; set; }
    public override string ToString()
    {
        string h = Hours.ToString("D2");
        if (h.Length == 1)
            h = "0" + h;
        return Hours.ToString("D2") + ":" + Minutes.ToString("D2");
    }

    public static Time Parse(string time)
    {
        Time t = new Time();
        t.Hours = 0;
        t.Minutes = 0;
        if (!string.IsNullOrEmpty(time))
        {
            time = time.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(" ", "").Trim(); // Remove whitespace chars
            if (time.IndexOf(",") >= 0 || time.IndexOf(".") >= 0 || time.IndexOf(":") < 0)
                throw new Exception("Not a valid time: " + time + " should be format hh:mm");
            string[] hm = time.Split(':');
            if (string.IsNullOrEmpty(hm[0]))
                hm[0] = "0";
            if (string.IsNullOrEmpty(hm[1]))
                hm[1] = "0";
            t.Hours = int.Parse(hm[0]);
            t.Minutes = int.Parse(hm[1]);
        }
        return t;
    }

    public static Time FromMinutes(int minutes)
    {
        int hours = minutes / 60;
        minutes -= (hours * 60);
        Time t = new Time();
        t.Hours = hours;
        t.Minutes = minutes;
        return t;
    }

    public int getTotalMinutes()
    {
        return Hours * 60 + Minutes;
    }

}

类 MaskedTextBoxMinutes:

    class MaskedTextBoxMinutes : MaskedTextBox
    {
        public override string Text
        {
            get
            {
                Time t = Time.Parse(base.Text);
                return t.getTotalMinutes().ToString();
            }
            set
            {
                int minutes = 0;
                int.TryParse(value, out minutes);
                base.Text = Time.FromMinutes(minutes).ToString();
            }
        }
    }

类MaksedEditControl:

class MaskedEditingControl : MaskedTextBoxMinutes, IDataGridViewEditingControl
{
    private DataGridView dataGridViewControl;
    private bool valueIsChanged = false;
    private int rowIndexNum;

    public MaskedEditingControl() : base()
    {
        this.Mask = "00:00";
        this.InsertKeyMode = InsertKeyMode.Overwrite;
    }

    public object EditingControlFormattedValue
    {
        get { return this.Text; }
        set { this.Text = value.ToString(); }
    }
    public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
    {
        return true;
    }
    public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
    {
        return this.Text;
    }
    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
    {

        this.Font = dataGridViewCellStyle.Font;
        this.ForeColor = dataGridViewCellStyle.ForeColor;
        this.BackColor = dataGridViewCellStyle.BackColor;
    }
    public int EditingControlRowIndex
    {
        get { return rowIndexNum; }
        set { rowIndexNum = value; }
    }
    public void PrepareEditingControlForEdit(bool selectAll)
    {
        // No preparation needs to be done.
    }
    public bool RepositionEditingControlOnValueChange
    {
        get { return false; }
    }
    public DataGridView EditingControlDataGridView
    {
        get { return dataGridViewControl; }
        set { dataGridViewControl = value; }
    }

    public bool EditingControlValueChanged
    {
        get { return valueIsChanged; }
        set { valueIsChanged = value; }
    }
    public Cursor EditingControlCursor
    {
        get { return base.Cursor; }
    }
    Cursor IDataGridViewEditingControl.EditingPanelCursor
    {
        get { return EditingControlCursor; }
    }
    protected override void OnTextChanged(System.EventArgs e)
    {
        // Notify the DataGridView that the contents of the cell have changed.
        valueIsChanged = true;
        if (this.EditingControlDataGridView!=null)
          this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
        base.OnTextChanged(e);
    }
}

类 MaskedEditColumn:

public class MaskedEditColumn : DataGridViewColumn
{
    public MaskedEditColumn()
        : base(new MaskedEditCell())
    {
    }
    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if ((value != null) && !value.GetType().IsAssignableFrom(typeof(MaskedEditCell)))
            {
                throw new InvalidCastException("Must be a MaskedEditCell");
            }
            base.CellTemplate = value;
        }
    }

    private MaskedEditCell MaskedEditCellTemplate
    {
        get { return this.CellTemplate as MaskedEditCell; }
    }
}

类 MaskedEditCell:

public class MaskedEditCell : DataGridViewTextBoxCell
{
    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // Set the value of the editing control to the current cell value.
        base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
        MaskedEditColumn mecol = (MaskedEditColumn)OwningColumn;
        MaskedEditingControl ctl = (MaskedEditingControl)DataGridView.EditingControl;
        ctl.Text = this.Value.ToString();
    }
    public override Type EditType
    {
        // Return the type of the editing contol that CalendarCell uses.
        get { return typeof(MaskedEditingControl); }
    }
    public override Type ValueType
    {
        // Return the type of the value that CalendarCell contains.
        get { return typeof(string); }
    }
    public override object DefaultNewRowValue
    {
        // Use the current date and time as the default value.
        get { return ""; }
    }
    protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, System.Windows.Forms.DataGridViewElementStates cellState, object value, object formattedValue, string errorText, System.Windows.Forms.DataGridViewCellStyle cellStyle, System.Windows.Forms.DataGridViewAdvancedBorderStyle advancedBorderStyle,
    System.Windows.Forms.DataGridViewPaintParts paintParts)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle,
        paintParts);
    }
}

最好的问候 汉斯·米林...

【问题讨论】:

  • 查看 DataGridView CellParsing 和 CellFormatting 事件。您可以格式化显示的值,但基础数据不会更改。
  • @Crowcoder - 我知道这是一篇很老的帖子,但我很难找到在 VB.NET 中工作的类似内容,即使在我转换之后也是如此。另外,我是这类事情的新手,并不太了解这些代码。我希望你能引导我朝着正确的方向前进,因为我可以复制/粘贴到我项目中的类模块中并让它工作? (可能不是,嗯)
  • @braX,这太模糊了。考虑问你自己的问题。提供完整的错误详情和a mcve

标签: c# winforms datagridview datatable maskedtextbox


【解决方案1】:

感谢 Crowcoder,我通过使用 CellFormatting 事件解决了这个问题:

    private void dgvTidsregistrering_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        DataGridView dgv = (DataGridView)sender;
        if (dgv.Columns[e.ColumnIndex].CellType == typeof(MaskedEditCell))
        {
            double minutes = 0;
            if (e.Value is double)
                minutes = Convert.ToInt32(e.Value);
            else
            {
                if (e.Value == DBNull.Value)
                    minutes = 0;
                else
                    double.TryParse((string)e.Value, out minutes);
            }
            Time t = Time.FromMinutes((int)minutes);
            e.Value = t.ToString();
        }
    }

【讨论】:

  • 这是我唯一能找到的甚至接近我想做的事情,但我使用的是 VB.NET(我尝试翻译代码,它似乎工作,但添加时出错到我的项目) - 我不擅长创建自定义类也不擅长创建自定义控件,这无济于事。
猜你喜欢
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
相关资源
最近更新 更多