Saltar al contenido principal

 none
Personalizar DataGridView RRS feed

  • Pregunta

  • Estimados, tengo la siguiente duda, he creado un control personalizado en el cual tengo un boton incrustado en un textbox, este control funciona perfectamente por si solo, luego utilice este control como base para crear una nueva columna en un DataGridView, lo cual funciono tambien y aparece la columna con el formato del control, mi problema es que no se como poder llamar al evento click que agregue al boton que esta dentro del textbox una vez que este esta como columna en el datagridview, dejo el código para que se hagan una idea de lo que hice y para ver si me pueden ayudar.

    Control TextBoxbutton

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace DataGridViewPowered
    {
        public class TextBoxbutton : TextBox
        {
            private readonly Button _button;
    
            public TextBoxbutton()
            {
                _button = new Button {
                    Cursor = Cursors.Default,
                    TabStop = false,
                    FlatStyle = FlatStyle.Flat
                };
                this.Controls.Add(_button);
                PosicionarBoton();
            }
    
            protected override void OnResize(EventArgs e)
            {
                base.OnResize(e);
                PosicionarBoton();
            }
    
            private void PosicionarBoton()
            {
                _button.Size = new Size(this.ClientSize.Height, this.ClientSize.Height);
                _button.Location = new Point(this.ClientSize.Width - _button.Width, 0);
                SendMessage(this.Handle, 0xd3, (IntPtr)2, (IntPtr)(_button.Width << 16));
            }
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    
            [Category("Action")]
            public event EventHandler ButtonClick
            {
                add { _button.Click += value; }
                remove { _button.Click -= value; }
            }
    
            private Image _buttonImage;
    
            [Category("Appearance"), Description("Imagen del botón")]
            public Image ButtonImage
            {
                get
                {
                    return _buttonImage;
                }
                set
                {
                    _buttonImage = value;
                    if (_buttonImage == null)
                        _button.BackgroundImage = Properties.Resources.Elipsis;
                    else
                        _button.BackgroundImage = _buttonImage;
                }
            }
        }
    }
    

    TextButtonCell

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.ComponentModel;
    
    namespace DataGridViewPowered
    {
        public class TextButtonCell : DataGridViewTextBoxCell
        {        
            public TextButtonCell() : base()
            { 
            }
    
            public override void InitializeEditingControl(int rowIndex, object
            initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue,
                dataGridViewCellStyle);
                TextButtonEditingControl ctl =
                DataGridView.EditingControl as TextButtonEditingControl;
    
    
                if (this.Value == null)
                {
                    ctl.Text = "";
                }
                else
                {
                    ctl.Text = this.Value.ToString();
                }
            }
    
            public override Type EditType
            {
                get
                {
                    return typeof(TextButtonEditingControl);
                }
            }
    
            public override Type ValueType
            {
                get
                {
                    return typeof(string);
                }
            }
    
            public override object DefaultNewRowValue
            {
                get
                {
                    // Retrona vallor vacio por defecto
                    return "";
                }
            }
    
            
    
    
        }
    }
    

    TextButtonColumn

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace DataGridViewPowered
    {
        public class TextButtonColumn: DataGridViewColumn
        {
            public TextButtonColumn() : base(new TextButtonCell())
            {}
    
            public override DataGridViewCell CellTemplate
            {
                get
                {
                    return base.CellTemplate;
                }
                set
                {
                    if (value != null &&
                    !value.GetType().IsAssignableFrom(typeof(TextButtonCell)))
                    {
                        throw new InvalidCastException("Debe utilizar una celda del tipo TextButton");
                    }
                    base.CellTemplate = value;
                }
            }
        }
    }
    

    TextButtonEditingControl

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace DataGridViewPowered
    {
        class TextButtonEditingControl :TextBoxbutton, IDataGridViewEditingControl
        {
            DataGridView dataGridView;
            private bool TextChanged = false;
            int rowIndex;
    
            public TextButtonEditingControl()
            { 
    
            }
    
            public object EditingControlFormattedValue
            {
                get
                {
                    return this.Text;
                }
                set
                {
                    try
                    {
                        this.Text = "";
                    }
                    catch
                    {
                        this.Text = "";
                    }
                }
            }
    
            public object GetEditingControlFormattedValue(
            DataGridViewDataErrorContexts context)
            {
                return EditingControlFormattedValue;
            }
    
            public void ApplyCellStyleToEditingControl(
            DataGridViewCellStyle dataGridViewCellStyle)
            {
                this.Font = dataGridViewCellStyle.Font;
                this.ButtonImage = Properties.Resources.Elipsis;
            }
    
            public int EditingControlRowIndex
            {
                get
                {
                    return rowIndex;
                }
                set
                {
                    rowIndex = value;
                }
            }
    
            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
                {
                    return dataGridView;
                }
                set
                {
                    dataGridView = value;
                }
            }
    
            public bool EditingControlValueChanged
            {
                get
                {
                    return TextChanged;
                }
                set
                {
                    TextChanged = value;
                }
            }
    
            public Cursor EditingPanelCursor
            {
                get
                {
                    return base.Cursor;
                }
            }
    
            protected override void OnTextChanged(EventArgs eventargs)
            {
                TextChanged = true;
                this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                base.OnTextChanged(eventargs);
            }
    
            
    
        }
    }
    

    martes, 16 de febrero de 2016 16:32

Respuestas

  • La forma más sencilla es utilizar el evento CellContentClick como hace el DataGridViewButtonColumn, en lugar de crear un nuevo evento a nivel del DataGridView.

    Puedes hacerlo suscribiéndote al evento ButtonClick del EditingControl en el método InitializeEditingControl de la celda y generar el evento CellContentClick a través del método RaiseCellContentClick:

            public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
                TextBoxButton textBoxButton = DataGridView.EditingControl as TextBoxButton;
                if (textBoxButton != null) textBoxButton.ButtonClick += OnButtonClick;
            }
    
            private void OnButtonClick(object sender, EventArgs e)
            {
                if (DataGridView != null &&
                    ColumnIndex < DataGridView.Columns.Count &&
                    RowIndex < DataGridView.Rows.Count)
                {
                    RaiseCellContentClick(new DataGridViewCellEventArgs(ColumnIndex, RowIndex));
                }
            }

    Entre hoy y mañana espero publicar un ejemplo funcionando en mi blog:

    Píldoras .NET


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    domingo, 28 de febrero de 2016 14:16

Todas las respuestas

  • La forma más sencilla es utilizar el evento CellContentClick como hace el DataGridViewButtonColumn, en lugar de crear un nuevo evento a nivel del DataGridView.

    Puedes hacerlo suscribiéndote al evento ButtonClick del EditingControl en el método InitializeEditingControl de la celda y generar el evento CellContentClick a través del método RaiseCellContentClick:

            public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
                TextBoxButton textBoxButton = DataGridView.EditingControl as TextBoxButton;
                if (textBoxButton != null) textBoxButton.ButtonClick += OnButtonClick;
            }
    
            private void OnButtonClick(object sender, EventArgs e)
            {
                if (DataGridView != null &&
                    ColumnIndex < DataGridView.Columns.Count &&
                    RowIndex < DataGridView.Rows.Count)
                {
                    RaiseCellContentClick(new DataGridViewCellEventArgs(ColumnIndex, RowIndex));
                }
            }

    Entre hoy y mañana espero publicar un ejemplo funcionando en mi blog:

    Píldoras .NET


    Píldoras .NET
    Artículos, tutoriales y ejemplos de código .NET

    Píldoras JS
    Artículos, tutoriales y ejemplos de código JavaScript, HTML5, CSS3, ...

    domingo, 28 de febrero de 2016 14:16
  • Asier, te pasaste por la respuesta muchas gracias, estaba con esta duda hace un rato y al parecer nadie la habia podido solucionar, gracias a esto voy a empezar a crear un nuevo set de controles personalizados para no tener que depender de librerías externas como infragistics o Devexpress 
    miércoles, 2 de marzo de 2016 14:10
  • Saludos, como pudo poner a funcionar el evento click del botón? aun no he podido
    viernes, 22 de noviembre de 2019 20:36
  • Me podrías decir como hiciste en el evento CellContentClick para que reconozca el click solo cuando le das al botón? a mi me lo reconoce en cualquier parte de la celda que haga click
    hace 18 horas 14 minutos