none
DataGridViewのユーザーコントロール表示について RRS feed

  • 質問

  • DataGridViewに以下のようなユーザーコントロールを1セルに表示したいと考えております。

    MaskedTextBox? | Button | Button
         [ [12:30][▲][▼] ]

    列を分けて設定することはできているのですが、上記のような場合ユーザーコントロールを作成してグリッドに設定するのでしょうか?

    DateTimePickerやMaskedTextBoxをセルに設定するサンプルは拝見しましたが、複数の場合はどのようにするのでしょうか。

    ご教授のほど、よろしくお願いいたします。

    2016年7月30日 15:33

回答

  • DateTimePickerやMaskedTextBoxの場合と同様にUserControlにIDataGridViewEditingControlインターフェースをつけてEditingControlFormattedValueプロパティなどで値のやり取りができるようにします。
    ただし、ユーザーコントロールに複数のコントロールを配置したとしてもセルの値は1つだけでるため1つの値のみしかやり取りはできません。
    複数の値をやり取りしたい場合はセルの値をクラスにするなど工夫する必要があります。
    #WPFなら1セルで複数の値をやり取りするのは簡単です

    using System;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                DataGridView dgv;
                dgv = new DataGridView();
                dgv.Dock = DockStyle.Fill;
                var column1 = new CustomControlColumn<EditControl.NullableTimePickerEditingControl, TimeSpan>();
                column1.DataPropertyName = "Column1";
                column1.DefaultCellStyle.Format = "hh\\:mm";
                dgv.Columns.Add(column1);
                this.Controls.Add(dgv);
    
    
                var column2 = new CustomControlColumn<EditControl.UpDownMaskTextBoxEditingControl, string>();
                column2.DataPropertyName = "Column2";
                column2.DefaultCellStyle.Format = "hh\\:mm";
                dgv.Columns.Add(column2);
                this.Controls.Add(dgv);
    
                DataTable table;
                table = new DataTable();
                table.Columns.Add(new DataColumn("Column1", typeof(TimeSpan)));
                table.Columns.Add(new DataColumn("Column2", typeof(string)));
                table.Rows.Add(new TimeSpan(12, 30, 00), "12:34");
                table.Rows.Add(new TimeSpan(00, 59, 00), "56%");
    
                dgv.EditingControlShowing += dgv_EditingControlShowing;
    
                dgv.DataSource = table;
    
            }
    
            void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                var dgv = (DataGridView)sender;
                if (e.Control is EditControl.UpDownMaskTextBoxEditingControl)
                {
                    var edit = ((EditControl.UpDownMaskTextBoxEditingControl)e.Control);
                    if (dgv.CurrentRow.Index == 1)
                    {
                        edit.Mask = "00%";
                    }
                    else
                    {
                        edit.Mask = "00:00";
                    }
                }
            }
        }
    
        namespace EditControl
        {
            /// <summary> DataGridViewで表示させたいUserControl</summary>
            class NullableTimePicker : UserControl
            {
                public NullableTimePicker()
                {
                    DateTimePicker picker = new DateTimePicker();
                    picker.Format = DateTimePickerFormat.Custom;
                    picker.ShowUpDown = true;
                    picker.ShowCheckBox = true;
                    picker.Dock = DockStyle.Top;
                    picker.CustomFormat = "HH:mm";
                    picker.ValueChanged += (s, e) =>
                    {
                        if (picker.Checked)
                        {
                            picker.CustomFormat = "HH:mm";
                        }
                        else
                        {
                            picker.CustomFormat = "'<NULL>'";
                        }
                    };
                    picker.Checked = true;
                    this.Controls.Add(picker);
    
                    MaskedTextBox mtb = new MaskedTextBox();
                    mtb.Text = "MaskedTexBox";
                    mtb.Top = picker.Height;
                    mtb.BackColor = Color.LightPink;
                    this.Controls.Add(mtb);
    
                    this.Height = mtb.Top + mtb.Height;
                    this.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
    
                    this.DateTimePicker = picker;
                }
    
                public TimeSpan? Value
                {
                    get
                    {
                        return this.DateTimePicker.Checked ? (TimeSpan?)this.DateTimePicker.Value.TimeOfDay : null;
                    }
                    set
                    {
                        if (value == null)
                        {
                            this.DateTimePicker.Checked = false;
                        }
                        else
                        {
                            this.DateTimePicker.Checked = true;
                            this.DateTimePicker.Value = DateTime.Now.Date + value.Value;
                        }
                    }
                }
    
                protected DateTimePicker DateTimePicker { get; private set; }
            }
    
    
            /// <summary>DataGridViewで表示させたいUserControlにIDataGridViewEditingControlインターフェースを実装する</summary>
            class NullableTimePickerEditingControl : NullableTimePicker, IDataGridViewEditingControl
            {
                private bool valueChanged = false;
    
                public NullableTimePickerEditingControl()
                {
                    this.DateTimePicker.ValueChanged += DateTimePicker_ValueChanged;
                }
    
                public object EditingControlFormattedValue
                {
                    get
                    {
                        return this.Value;
                    }
                    set
                    {
                        if (value is TimeSpan)
                        {
                            this.Value = (TimeSpan)value;
                        }
                        else if (value is String)
                        {
                            if (string.IsNullOrEmpty((string)value))
                            {
                                this.Value = null;
                            }
                            else
                            {
                                try
                                {
                                    this.Value = TimeSpan.Parse((String)value);
                                }
                                catch
                                {
                                    this.Value = DateTime.Now.TimeOfDay;
                                }
                            }
                        }
                        else
                        {
                            this.Value = null;
                        }
                    }
                }
    
                public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
                {
                    //nullは空白表示に
                    TimeSpan? value = (TimeSpan?)this.EditingControlFormattedValue;
                    return value == null ? string.Empty : value.Value.ToString(this.EditingControlDataGridView.CurrentCell.Style.Format);
                }
    
                public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
                {
                    this.Font = dataGridViewCellStyle.Font;
                    this.DateTimePicker.CalendarForeColor = dataGridViewCellStyle.ForeColor;
                    this.DateTimePicker.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
                }
    
                public int EditingControlRowIndex { get; set; }
    
                public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
                {
                    switch (key & Keys.KeyCode)
                    {
                        case Keys.Left:
                        case Keys.Up:
                        case Keys.Down:
                        case Keys.Right:
                        case Keys.Home:
                        case Keys.End:
                        case Keys.PageDown:
                        case Keys.PageUp:
                            return true;
                        default:
                            return !dataGridViewWantsInputKey;
                    }
                }
    
                public void PrepareEditingControlForEdit(bool selectAll) { }
    
                public bool RepositionEditingControlOnValueChange { get { return false; } }
    
                public DataGridView EditingControlDataGridView { get; set; }
    
                public bool EditingControlValueChanged { get; set; }
    
                public Cursor EditingPanelCursor { get { return base.Cursor; } }
    
                void DateTimePicker_ValueChanged(object sender, EventArgs e)
                {
                    valueChanged = true;
                    this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                }
            }
    
    
            class UpDownMaskTextBox : UserControl
            {
                private MaskedTextBox masked;
                private Timer timer;
                public UpDownMaskTextBox()
                {
                    int w = 0;
                    foreach (string buttonText in new string[] { "▲", "▼" })
                    {
                        Button btn = new Button();
    
                        btn.Font = new System.Drawing.Font(this.Font.FontFamily, 8f);
                        btn.Text = buttonText;
                        btn.AutoSize = true;
                        btn.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                        btn.Dock = DockStyle.Right;
                        this.Controls.Add(btn);
                        w += btn.Width;
    
                        btn.MouseDown += (sender, e) =>
                            {
                                var b = (Button)sender;
                                b.Capture = true;
                                timer = new Timer();
                                timer.Tick += timer_Tick;
                                timer.Interval = 1000;
                                if (b.Text == "▲")
                                {
                                    timer.Tag = true;
                                    UpDown(true);
                                }
                                else
                                {
                                    timer.Tag = false;
                                    UpDown(false);
                                }
    
                                timer.Start();
    
                            };
                        btn.MouseUp += (sender, e) =>
                            {
                                if (timer != null)
                                {
                                    timer.Stop();
                                    timer.Dispose();
                                    timer = null;
                                }
                            };
                    }
    
                    masked = new MaskedTextBox();
                    masked.HidePromptOnLeave = false;
                    masked.HideSelection = false;
                    masked.Width = this.Width - w;
                    masked.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    masked.TextMaskFormat = MaskFormat.IncludePromptAndLiterals;
                    masked.Mask = "00:00";
                    masked.TextChanged += (sender, e) =>
                        {
                            this.OnTextChanged(EventArgs.Empty);
                        };
                    this.Controls.Add(masked);
                }
    
                void timer_Tick(object sender, EventArgs e)
                {
                    var timer = (Timer)sender;
                    timer.Interval =100;
                    UpDown((bool)timer.Tag);
                }
                void UpDown(bool up)
                {
                    int diff = up ? 1 : -1;
                    int start = this.masked.SelectionStart;
                    if (start == this.masked.Text.Length)
                    {
                        start -= 1;
                        this.masked.SelectionStart = start;
                    }
                    masked.SelectionLength = 1;
                    int n = 0;
                    if (int.TryParse(masked.SelectedText, out n))
                    {
                        n = (((n + diff) % 10) + 10) % 10;
                    }
                    masked.Text = masked.Text.Substring(0, start) + n.ToString() + masked.Text.Substring(start + 1);
                    masked.SelectionStart = start;
                    masked.SelectionLength = 1;
                }
    
    
                public string Value
                {
                    get
                    {
                        return masked.Text;
                    }
                    set
                    {
                        masked.Text = value;
                    }
                }
    
                public virtual string Mask
                {
                    get { return masked.Mask; }
                    set { masked.Mask = value; }
                }
    
                protected MaskedTextBox MaskedTextBox { get { return masked; } }
            }
            class UpDownMaskTextBoxEditingControl : UpDownMaskTextBox, IDataGridViewEditingControl
            {
                private bool valueChanged = false;
                private bool prepare = false;
    
                public override string Mask { get; set; }
    
                public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
                {
                    prepare = true;
                }
                public object EditingControlFormattedValue
                {
                    get
                    {
                        return _EditingControlFormattedValue;
                    }
                    set
                    {
                        _EditingControlFormattedValue = (string)value;
                    }
                }
                private object _EditingControlFormattedValue;
                public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
                {
                    return EditingControlFormattedValue.ToString();
                }
                public int EditingControlRowIndex { get; set; }
    
                public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
                {
                    switch (key & Keys.KeyCode)
                    {
                        case Keys.Left:
                        case Keys.Up:
                        case Keys.Down:
                        case Keys.Right:
                        case Keys.Home:
                        case Keys.End:
                        case Keys.PageDown:
                        case Keys.PageUp:
                            return true;
                        default:
                            return !dataGridViewWantsInputKey;
                    }
                }
    
    
    
                public void PrepareEditingControlForEdit(bool selectAll)
                {
                    base.Mask = this.Mask;
                    base.Value = (string)this.EditingControlFormattedValue;
                    valueChanged = false;
                    base.MaskedTextBox.SelectionStart = 0;
                    base.MaskedTextBox.SelectionLength = 1;
                    prepare = false;
                }
    
                public bool RepositionEditingControlOnValueChange { get { return false; } }
    
                public DataGridView EditingControlDataGridView { get; set; }
    
                public bool EditingControlValueChanged { get; set; }
    
                public Cursor EditingPanelCursor { get { return base.Cursor; } }
    
                protected override void OnTextChanged(EventArgs e)
                {
                    if (!prepare)
                    {
                        _EditingControlFormattedValue = this.Value;
                        valueChanged = true;
                        this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                        base.OnTextChanged(e);
                    }
                }
            }
        }
    
        /// <summary>
        /// UserControlを表示させるためのColumn
        /// </summary>
        /// <typeparam name="TControl">編集時に表示させたいコントロール</typeparam>
        /// <typeparam name="TValue">列の値の型</typeparam>
        public class CustomControlColumn<TControl, TValue>
            : DataGridViewColumn
            where TControl : Control, IDataGridViewEditingControl
        {
            public CustomControlColumn()
                : base(new CustomControlCell<TControl, TValue>())
            {
            }
    
            public override DataGridViewCell CellTemplate
            {
                get { return base.CellTemplate; }
                set
                {
                    if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomControlCell<TControl, TValue>)))
                    {
                        throw new InvalidCastException("Must be a CalendarCell");
                    }
                    base.CellTemplate = value;
                }
            }
        }
    
        /// <summary>
        /// UserControlを表示させるためのセル
        /// </summary>
        /// <typeparam name="TControl">編集時に表示させたいコントロール</typeparam>
        /// <typeparam name="TValue">セルの値の型</typeparam>
        public class CustomControlCell<TControl, TValue> : DataGridViewTextBoxCell where TControl : Control, IDataGridViewEditingControl
        {
            public override void InitializeEditingControl(int rowIndex, object
                initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
    
                var ctl = (IDataGridViewEditingControl)DataGridView.EditingControl;
                ctl.EditingControlFormattedValue = initialFormattedValue;
            }
    
            public override Type EditType { get { return typeof(TControl); } }
    
            public override Type ValueType
            {
                get { return typeof(TValue); }
            }
    
            public override object DefaultNewRowValue
            {
                get { return default(TValue); }
            }
    
            protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
            {
                base.OnKeyDown(e, rowIndex);
    
                if (e.KeyCode == Keys.Delete)
                {
                    this.Value = DBNull.Value;
                }
            }
            public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
            {
                //編集パネルの大きさ変更の
                cellBounds.Height = Math.Max(cellBounds.Height, this.DataGridView.EditingControl.PreferredSize.Height);
                cellClip.Height = cellBounds.Height;
    
                base.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);
            }
        }
    }
    
    

    2016/07/31 20:52
    UpDownMaskTextBoxEditingControlを追加


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2016年7月30日 19:03

すべての返信

  • DateTimePickerやMaskedTextBoxの場合と同様にUserControlにIDataGridViewEditingControlインターフェースをつけてEditingControlFormattedValueプロパティなどで値のやり取りができるようにします。
    ただし、ユーザーコントロールに複数のコントロールを配置したとしてもセルの値は1つだけでるため1つの値のみしかやり取りはできません。
    複数の値をやり取りしたい場合はセルの値をクラスにするなど工夫する必要があります。
    #WPFなら1セルで複数の値をやり取りするのは簡単です

    using System;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                DataGridView dgv;
                dgv = new DataGridView();
                dgv.Dock = DockStyle.Fill;
                var column1 = new CustomControlColumn<EditControl.NullableTimePickerEditingControl, TimeSpan>();
                column1.DataPropertyName = "Column1";
                column1.DefaultCellStyle.Format = "hh\\:mm";
                dgv.Columns.Add(column1);
                this.Controls.Add(dgv);
    
    
                var column2 = new CustomControlColumn<EditControl.UpDownMaskTextBoxEditingControl, string>();
                column2.DataPropertyName = "Column2";
                column2.DefaultCellStyle.Format = "hh\\:mm";
                dgv.Columns.Add(column2);
                this.Controls.Add(dgv);
    
                DataTable table;
                table = new DataTable();
                table.Columns.Add(new DataColumn("Column1", typeof(TimeSpan)));
                table.Columns.Add(new DataColumn("Column2", typeof(string)));
                table.Rows.Add(new TimeSpan(12, 30, 00), "12:34");
                table.Rows.Add(new TimeSpan(00, 59, 00), "56%");
    
                dgv.EditingControlShowing += dgv_EditingControlShowing;
    
                dgv.DataSource = table;
    
            }
    
            void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                var dgv = (DataGridView)sender;
                if (e.Control is EditControl.UpDownMaskTextBoxEditingControl)
                {
                    var edit = ((EditControl.UpDownMaskTextBoxEditingControl)e.Control);
                    if (dgv.CurrentRow.Index == 1)
                    {
                        edit.Mask = "00%";
                    }
                    else
                    {
                        edit.Mask = "00:00";
                    }
                }
            }
        }
    
        namespace EditControl
        {
            /// <summary> DataGridViewで表示させたいUserControl</summary>
            class NullableTimePicker : UserControl
            {
                public NullableTimePicker()
                {
                    DateTimePicker picker = new DateTimePicker();
                    picker.Format = DateTimePickerFormat.Custom;
                    picker.ShowUpDown = true;
                    picker.ShowCheckBox = true;
                    picker.Dock = DockStyle.Top;
                    picker.CustomFormat = "HH:mm";
                    picker.ValueChanged += (s, e) =>
                    {
                        if (picker.Checked)
                        {
                            picker.CustomFormat = "HH:mm";
                        }
                        else
                        {
                            picker.CustomFormat = "'<NULL>'";
                        }
                    };
                    picker.Checked = true;
                    this.Controls.Add(picker);
    
                    MaskedTextBox mtb = new MaskedTextBox();
                    mtb.Text = "MaskedTexBox";
                    mtb.Top = picker.Height;
                    mtb.BackColor = Color.LightPink;
                    this.Controls.Add(mtb);
    
                    this.Height = mtb.Top + mtb.Height;
                    this.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
    
                    this.DateTimePicker = picker;
                }
    
                public TimeSpan? Value
                {
                    get
                    {
                        return this.DateTimePicker.Checked ? (TimeSpan?)this.DateTimePicker.Value.TimeOfDay : null;
                    }
                    set
                    {
                        if (value == null)
                        {
                            this.DateTimePicker.Checked = false;
                        }
                        else
                        {
                            this.DateTimePicker.Checked = true;
                            this.DateTimePicker.Value = DateTime.Now.Date + value.Value;
                        }
                    }
                }
    
                protected DateTimePicker DateTimePicker { get; private set; }
            }
    
    
            /// <summary>DataGridViewで表示させたいUserControlにIDataGridViewEditingControlインターフェースを実装する</summary>
            class NullableTimePickerEditingControl : NullableTimePicker, IDataGridViewEditingControl
            {
                private bool valueChanged = false;
    
                public NullableTimePickerEditingControl()
                {
                    this.DateTimePicker.ValueChanged += DateTimePicker_ValueChanged;
                }
    
                public object EditingControlFormattedValue
                {
                    get
                    {
                        return this.Value;
                    }
                    set
                    {
                        if (value is TimeSpan)
                        {
                            this.Value = (TimeSpan)value;
                        }
                        else if (value is String)
                        {
                            if (string.IsNullOrEmpty((string)value))
                            {
                                this.Value = null;
                            }
                            else
                            {
                                try
                                {
                                    this.Value = TimeSpan.Parse((String)value);
                                }
                                catch
                                {
                                    this.Value = DateTime.Now.TimeOfDay;
                                }
                            }
                        }
                        else
                        {
                            this.Value = null;
                        }
                    }
                }
    
                public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
                {
                    //nullは空白表示に
                    TimeSpan? value = (TimeSpan?)this.EditingControlFormattedValue;
                    return value == null ? string.Empty : value.Value.ToString(this.EditingControlDataGridView.CurrentCell.Style.Format);
                }
    
                public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
                {
                    this.Font = dataGridViewCellStyle.Font;
                    this.DateTimePicker.CalendarForeColor = dataGridViewCellStyle.ForeColor;
                    this.DateTimePicker.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
                }
    
                public int EditingControlRowIndex { get; set; }
    
                public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
                {
                    switch (key & Keys.KeyCode)
                    {
                        case Keys.Left:
                        case Keys.Up:
                        case Keys.Down:
                        case Keys.Right:
                        case Keys.Home:
                        case Keys.End:
                        case Keys.PageDown:
                        case Keys.PageUp:
                            return true;
                        default:
                            return !dataGridViewWantsInputKey;
                    }
                }
    
                public void PrepareEditingControlForEdit(bool selectAll) { }
    
                public bool RepositionEditingControlOnValueChange { get { return false; } }
    
                public DataGridView EditingControlDataGridView { get; set; }
    
                public bool EditingControlValueChanged { get; set; }
    
                public Cursor EditingPanelCursor { get { return base.Cursor; } }
    
                void DateTimePicker_ValueChanged(object sender, EventArgs e)
                {
                    valueChanged = true;
                    this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                }
            }
    
    
            class UpDownMaskTextBox : UserControl
            {
                private MaskedTextBox masked;
                private Timer timer;
                public UpDownMaskTextBox()
                {
                    int w = 0;
                    foreach (string buttonText in new string[] { "▲", "▼" })
                    {
                        Button btn = new Button();
    
                        btn.Font = new System.Drawing.Font(this.Font.FontFamily, 8f);
                        btn.Text = buttonText;
                        btn.AutoSize = true;
                        btn.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
                        btn.Dock = DockStyle.Right;
                        this.Controls.Add(btn);
                        w += btn.Width;
    
                        btn.MouseDown += (sender, e) =>
                            {
                                var b = (Button)sender;
                                b.Capture = true;
                                timer = new Timer();
                                timer.Tick += timer_Tick;
                                timer.Interval = 1000;
                                if (b.Text == "▲")
                                {
                                    timer.Tag = true;
                                    UpDown(true);
                                }
                                else
                                {
                                    timer.Tag = false;
                                    UpDown(false);
                                }
    
                                timer.Start();
    
                            };
                        btn.MouseUp += (sender, e) =>
                            {
                                if (timer != null)
                                {
                                    timer.Stop();
                                    timer.Dispose();
                                    timer = null;
                                }
                            };
                    }
    
                    masked = new MaskedTextBox();
                    masked.HidePromptOnLeave = false;
                    masked.HideSelection = false;
                    masked.Width = this.Width - w;
                    masked.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    masked.TextMaskFormat = MaskFormat.IncludePromptAndLiterals;
                    masked.Mask = "00:00";
                    masked.TextChanged += (sender, e) =>
                        {
                            this.OnTextChanged(EventArgs.Empty);
                        };
                    this.Controls.Add(masked);
                }
    
                void timer_Tick(object sender, EventArgs e)
                {
                    var timer = (Timer)sender;
                    timer.Interval =100;
                    UpDown((bool)timer.Tag);
                }
                void UpDown(bool up)
                {
                    int diff = up ? 1 : -1;
                    int start = this.masked.SelectionStart;
                    if (start == this.masked.Text.Length)
                    {
                        start -= 1;
                        this.masked.SelectionStart = start;
                    }
                    masked.SelectionLength = 1;
                    int n = 0;
                    if (int.TryParse(masked.SelectedText, out n))
                    {
                        n = (((n + diff) % 10) + 10) % 10;
                    }
                    masked.Text = masked.Text.Substring(0, start) + n.ToString() + masked.Text.Substring(start + 1);
                    masked.SelectionStart = start;
                    masked.SelectionLength = 1;
                }
    
    
                public string Value
                {
                    get
                    {
                        return masked.Text;
                    }
                    set
                    {
                        masked.Text = value;
                    }
                }
    
                public virtual string Mask
                {
                    get { return masked.Mask; }
                    set { masked.Mask = value; }
                }
    
                protected MaskedTextBox MaskedTextBox { get { return masked; } }
            }
            class UpDownMaskTextBoxEditingControl : UpDownMaskTextBox, IDataGridViewEditingControl
            {
                private bool valueChanged = false;
                private bool prepare = false;
    
                public override string Mask { get; set; }
    
                public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
                {
                    prepare = true;
                }
                public object EditingControlFormattedValue
                {
                    get
                    {
                        return _EditingControlFormattedValue;
                    }
                    set
                    {
                        _EditingControlFormattedValue = (string)value;
                    }
                }
                private object _EditingControlFormattedValue;
                public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
                {
                    return EditingControlFormattedValue.ToString();
                }
                public int EditingControlRowIndex { get; set; }
    
                public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
                {
                    switch (key & Keys.KeyCode)
                    {
                        case Keys.Left:
                        case Keys.Up:
                        case Keys.Down:
                        case Keys.Right:
                        case Keys.Home:
                        case Keys.End:
                        case Keys.PageDown:
                        case Keys.PageUp:
                            return true;
                        default:
                            return !dataGridViewWantsInputKey;
                    }
                }
    
    
    
                public void PrepareEditingControlForEdit(bool selectAll)
                {
                    base.Mask = this.Mask;
                    base.Value = (string)this.EditingControlFormattedValue;
                    valueChanged = false;
                    base.MaskedTextBox.SelectionStart = 0;
                    base.MaskedTextBox.SelectionLength = 1;
                    prepare = false;
                }
    
                public bool RepositionEditingControlOnValueChange { get { return false; } }
    
                public DataGridView EditingControlDataGridView { get; set; }
    
                public bool EditingControlValueChanged { get; set; }
    
                public Cursor EditingPanelCursor { get { return base.Cursor; } }
    
                protected override void OnTextChanged(EventArgs e)
                {
                    if (!prepare)
                    {
                        _EditingControlFormattedValue = this.Value;
                        valueChanged = true;
                        this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                        base.OnTextChanged(e);
                    }
                }
            }
        }
    
        /// <summary>
        /// UserControlを表示させるためのColumn
        /// </summary>
        /// <typeparam name="TControl">編集時に表示させたいコントロール</typeparam>
        /// <typeparam name="TValue">列の値の型</typeparam>
        public class CustomControlColumn<TControl, TValue>
            : DataGridViewColumn
            where TControl : Control, IDataGridViewEditingControl
        {
            public CustomControlColumn()
                : base(new CustomControlCell<TControl, TValue>())
            {
            }
    
            public override DataGridViewCell CellTemplate
            {
                get { return base.CellTemplate; }
                set
                {
                    if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomControlCell<TControl, TValue>)))
                    {
                        throw new InvalidCastException("Must be a CalendarCell");
                    }
                    base.CellTemplate = value;
                }
            }
        }
    
        /// <summary>
        /// UserControlを表示させるためのセル
        /// </summary>
        /// <typeparam name="TControl">編集時に表示させたいコントロール</typeparam>
        /// <typeparam name="TValue">セルの値の型</typeparam>
        public class CustomControlCell<TControl, TValue> : DataGridViewTextBoxCell where TControl : Control, IDataGridViewEditingControl
        {
            public override void InitializeEditingControl(int rowIndex, object
                initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
    
                var ctl = (IDataGridViewEditingControl)DataGridView.EditingControl;
                ctl.EditingControlFormattedValue = initialFormattedValue;
            }
    
            public override Type EditType { get { return typeof(TControl); } }
    
            public override Type ValueType
            {
                get { return typeof(TValue); }
            }
    
            public override object DefaultNewRowValue
            {
                get { return default(TValue); }
            }
    
            protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
            {
                base.OnKeyDown(e, rowIndex);
    
                if (e.KeyCode == Keys.Delete)
                {
                    this.Value = DBNull.Value;
                }
            }
            public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
            {
                //編集パネルの大きさ変更の
                cellBounds.Height = Math.Max(cellBounds.Height, this.DataGridView.EditingControl.PreferredSize.Height);
                cellClip.Height = cellBounds.Height;
    
                base.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);
            }
        }
    }
    
    

    2016/07/31 20:52
    UpDownMaskTextBoxEditingControlを追加


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2016年7月30日 19:03
  • ご回答ありがとうございます。
    少し質問内容が伝わりにくかったようで申し訳ありません。

    ご回答頂いたサンプルではDateTimePickerを使用してUp/Downのボタンを表示しておりますが、
    テキスト部分はフォーマットを可変して表示したいと考えております。

    [12:30][▲][▼] や [25%][▲][▼] など

    この場合、UserControlのControlsに対してTextBox or MaskedTextBox、Button、Buttonの3コントロールをWidth/Height、Textなどを設定してAddするような感じでしょうか?
    ⇒Button.Clickイベントハンドラを実装してTextBoxを更新?


    2016年7月30日 20:04
  • gekkaさんのサンプルの応用で出来ると思いますよ。

    DataGridViewのセルにコントロールをホストする手順としては、
    下記の流れが基本になると思います。

    ①コントロール(UserControlを継承したり、Controlを継承したり)のクラスを定義する。
      ※サンプル上のNullableTimePickerクラス
    ②IDataGridViewEditingControlクラスを定義する。
      ※サンプル上のNullableTimePickerEditingControlクラス(IDataGridViewEditingControlインタフェースに従った各種やりとりメソッドを実装)
    ③DataGridViewColumnを継承したクラスを定義する。
      ※サンプル上のCustomControlColumnクラス
    ④DataGridViewTextBoxCellを継承したクラスを定義する
      ※サンプル上のCustomControlCellクラス(EditTypeプロパティのgetterに設定したEditingControlクラスが起動します。)

    その上で、テキスト部分は切り替えたいというお話であれば、
    ①と②をそのパターン毎に作成して、DataGridViewTextBoxCellのRowIndexの値等を判断材料としてEditTypeでreturnするEditingControlクラスを切り替えるのが良いかもしれません。

    ちなみにですが、ご質問されている下記の件は、その認識で方法は間違ってないです。
    「この場合、UserControlのControlsに対してTextBox or MaskedTextBox、Button、Buttonの3コントロールをWidth/Height、Textなどを設定してAddするような感じでしょうか?」

    ただし、普通にVisualStudio上で「ソリューションエクスプローラ」⇒「右クリック」⇒「追加」⇒「ユーザーコントロール」で表示されるデザイナ上に並べるだけかと思います。
    ※「そんな事わかってる」って話だったら申し訳ありませんが、質問を見るに全てコードでやろうとしている感じでしたので・・・

    私がお出ししたサンプルでないのに色々言うのは有れなのでこの辺で
    ※gekkaさん、変な事言ってたらご指摘下さい

    2016年7月31日 3:23
  • 上記の内容を踏まえてUserControlで作成してみたいと思います。

    ご回答ありがとうございました。

    2016年7月31日 11:21