title: Display and edit int column from datatable as hours and minutes in datagridview
body: <p>I have a database with a field that represents time in minutes. But in my datagridview I wan't to display the time as hh:mm. E.g. 130 minutes should display as 02:10, with a masked textbox when editing. I created a DataGridView and put a custum column class named MaskedTextboxMinutes in the time column, and created a custom control for handeling the editing. I only display the textbox when editing the cell, when not editing (i do not want the textbox to display when not editing the cell). When not editing the original int field value (e.g. 130) in minutes is displayed. The MaskedTextboxMinutes is created to it takes the minutes as input and output, but displays as hh:mm. Question is, where do I put some code to override the way the column is displayed? I would like to avoid overriding the onpaint.</p>
  
  <p>These are my classes for the MaskedTextBoxMinutes and the DataGridView Cell, Column and Control:</p>
  
  <p>Time class:</p>
  
  <pre><code>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(",") &gt;= 0 || time.IndexOf(".") &gt;= 0 || time.IndexOf(":") &lt; 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;
      }
  
  }
  </code></pre>
  
  <p>Class MaskedTextBoxMinutes:</p>
  
  <pre><code>    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();
              }
          }
      }
  </code></pre>
  
  <p>Class MaksedEditControl:</p>
  
  <pre><code>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);
      }
  }
  </code></pre>
  
  <p>Class MaskedEditColumn:</p>
  
  <pre><code>public class MaskedEditColumn : DataGridViewColumn
  {
      public MaskedEditColumn()
          : base(new MaskedEditCell())
      {
      }
      public override DataGridViewCell CellTemplate
      {
          get { return base.CellTemplate; }
          set
          {
              if ((value != null) &amp;&amp; !value.GetType().IsAssignableFrom(typeof(MaskedEditCell)))
              {
                  throw new InvalidCastException("Must be a MaskedEditCell");
              }
              base.CellTemplate = value;
          }
      }
  
      private MaskedEditCell MaskedEditCellTemplate
      {
          get { return this.CellTemplate as MaskedEditCell; }
      }
  }
  </code></pre>
  
  <p>Class MaskedEditCell:</p>
  
  <pre><code>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);
      }
  }
  </code></pre>
  
  <p>Best regards
    Hans Milling...</p>