Hit Test for CellClick event on GridView

6 posts, 0 answers
  1. Francisco
    Francisco avatar
    17 posts
    Member since:
    Mar 2016

    Posted 16 Mar Link to this post

    Hello,

      I have created a GridViewTextBoxColumn(), on _CellPaint() I am painting three images starting from the left to right.  I would like to detect a mouse click on the rectangle that corresponds to the image but I can't get the Cell.Size information on the CellClick() event.

    I have tried creating a custom control that holds three buttons but the UI doesn't fit my needs.

    In order to determine what was clicked on the cell, I need to know the click x/y and the current cell rectangle.

    Thanks!

     

    void grid_CellPaint(object sender, GridViewCellPaintEventArgs e)
            {
                GridDataCellElement dataCell = e.Cell as GridDataCellElement;
                if (dataCell != null && dataCell.ColumnInfo.FieldName == "ID")
                {
                    Size cellSize = e.Cell.Size;
                    Rectangle rct = new Rectangle(0, 0, cellSize.Height, cellSize.Height);
                    //using (Pen p = new Pen(Color.Black))
                   // {
                     
      //Flag
                        rct.Inflate(-2, -2);
                        e.Graphics.DrawImage(global::DIRC.UITools.Properties.Resources.Flag_red_icon16x16, rct);
               

                        //Information Icon
                        rct = new Rectangle(cellSize.Height, 0, cellSize.Height, cellSize.Height);
                
                        rct.Inflate(-2, -2);
                        e.Graphics.DrawImage(global::DIRC.UITools.Properties.Resources.information_icon_16x16, rct);

                        //Comment Icon
                        rct = new Rectangle(cellSize.Height * 2, 0, cellSize.Height, cellSize.Height);
                         
                        rct.Inflate(-2, -2);
                        e.Graphics.DrawImage(global::DIRC.UITools.Properties.Resources.comment_icon16x16, rct);
                   // }
                }
            }

  2. Francisco
    Francisco avatar
    17 posts
    Member since:
    Mar 2016

    Posted 16 Mar in reply to Francisco Link to this post

    I will take the approach of a custom GridDataCellElement with buttons.  Please disregard this post.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Hristo
    Admin
    Hristo avatar
    716 posts

    Posted 17 Mar Link to this post

    Hi Francisco,

    Thank you for writing.

    Indeed, creating a custom cell would be a better approach. Detailed information and examples are available here: http://docs.telerik.com/devtools/winforms/gridview/cells/creating-custom-cells.

    I hope this helps. Please let me know if you need further assistance.

    Regards,
    Hristo Merdjanov
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  5. Francisco
    Francisco avatar
    17 posts
    Member since:
    Mar 2016

    Posted 17 Mar in reply to Hristo Link to this post

    Hello Hristo,

      I looked at the example and what I came up is below.  Is there any way to improve it?

    Thanks

    - Francisco

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Telerik.WinControls.Layouts;
    using Telerik.WinControls.UI;
     
    namespace ABC.UITools
    {
        public class CustomGridDataCellElement : GridDataCellElement
        {
            private int _buttonCount = 3;
     
            public event EventHandler ButtonClick;
           
            public CustomGridDataCellElement(GridViewColumn column, GridRowElement row, int buttonCount)
                : base(column, row)
            {
                _buttonCount = buttonCount;
     
                for (int i = 0; i < _buttonCount; i++)
                {
                    RadButtonElement radButtonElement = new RadButtonElement();
                    radButtonElement.Name = "Button" + i.ToString("00");
                    radButtonElement.Tag = i;
                    radButtonElement.Click += new EventHandler(Button_Click);
                    radButtonElement.StretchVertically = true;
                    radButtonElement.StretchHorizontally = true;
                    radButtonElement.ShowBorder = false;
                    radButtonElement.ImageAlignment = ContentAlignment.TopLeft;
                    this.Children.Add(radButtonElement);
                }
            }
     
            protected override void CreateChildElements()
            {
                base.CreateChildElements();
            }
     
            private void Button_Click(object sender, EventArgs e)
            {
                this.OnButtonClick(sender, e);
            }
     
            public List<RadButtonElement> Buttons
            {
                get{
                    return this.Children.Where(b => b is RadButtonElement).Cast<RadButtonElement>().ToList();
                }
            }
     
            public override bool IsEditable
            {
                get { return false; }
            }
     
            protected virtual void OnButtonClick(object sender, EventArgs e)
            {
                if (this.ButtonClick != null)
                {
                    this.ButtonClick(sender, e);
                }
            }
     
            protected override void DisposeManagedResources()
            {
                foreach (var child in this.Children)
                {
                    if (child is RadButtonElement)
                    {
                        RadButtonElement btn = child as RadButtonElement;
                        btn.Click -= new EventHandler(Button_Click);
                    }
                }
                 base.DisposeManagedResources();
            }
     
            protected override SizeF ArrangeOverride(SizeF finalSize)
            {
                RectangleF clientRect = this.GetClientRectangle(finalSize);
                float buttonWidth = clientRect.Size.Width / this.Children.Count;
                RectangleF buttonFinalRect = new RectangleF(clientRect.Location, new SizeF(buttonWidth, clientRect.Height));
     
                foreach (RadButtonElement button in this.Children)
                {
                    button.Arrange(buttonFinalRect);
                    buttonFinalRect = new RectangleF(new PointF(buttonFinalRect.X + buttonWidth, buttonFinalRect.Y), buttonFinalRect.Size);
                }
     
                return finalSize;
            }
     
            protected override Type ThemeEffectiveType
            {
                get
                {
                    return typeof(GridDataCellElement);
                }
            }
     
            public override bool IsCompatible(GridViewColumn data, object context)
            {
                return data is TelerikCustomColumn && context is GridDataRowElement;
            }
        }
     
        public class TelerikCustomColumn : GridViewDataColumn
        {
            public TelerikCustomColumn(string fieldName)
                : base(fieldName)
            {
            }
     
            public override Type GetCellType(GridViewRowInfo row)
            {
                if (row is GridViewDataRowInfo)
                {
                    return typeof(CustomGridDataCellElement);
                }
                return base.GetCellType(row);
            }
        }
    }

    The idea is to have different options of number of buttons depending on the grid that it is being used on.  So for a grid column that needs 3 buttons I would create it like this;

    //When creating the grid template.  Width is determined based on the number of buttons to //be used * 20.  I will be using 16x16 bitmaps on the buttons.
      
    grid.MasterTemplate.Columns.Add(new TelerikCustomColumn("Actions") { AllowReorder = false, AllowResize = false, Width = 60, HeaderText = "", AllowSort = false });     

  6. Francisco
    Francisco avatar
    17 posts
    Member since:
    Mar 2016

    Posted 17 Mar in reply to Francisco Link to this post

    Sorry I hit Post before finishing.

    //On the CreateCell(object sender, GridViewCreateCellEventArgs e) event
    //I do this.
     
    TelerikCustomColumn dataColumn = e.Column as TelerikCustomColumn;
     
                if (e.Row is GridDataRowElement && dataColumn != null && e.Column.FieldName == "Actions")
                {
                    //Here I pass the number of buttons
                    CustomGridDataCellElement cell = new CustomGridDataCellElement(e.Column, e.Row, 3);
                    e.CellElement = cell;
                    //Load the button images.
                    List<RadButtonElement> btns = cell.Buttons;
                    foreach (var b in btns)
                    {
                        if (b.Tag != null)
                        {
                            b.DisplayStyle = DisplayStyle.Image;
                            b.ImageAlignment = ContentAlignment.MiddleCenter;
                            if ((int)b.Tag == 0)
                            {
                                b.Image = global::ABC.UITools.Properties.Resources.img01;
                            }
                            else if ((int)b.Tag == 1)
                            {
                                b.Image = global::ABC.UITools.Properties.Resources.img02;
                            }
                            else if ((int)b.Tag == 2)
                            {
                                b.Image = global::ABC.UITools.Properties.img03;
                            }
                        }
                    }
                    cell.ButtonClick += new EventHandler(cell_ButtonClick);
                }

    On the cell_ButtonClick..

    private void cell_ButtonClick(object sender, EventArgs e)
            {
                RadButtonElement button = sender as RadButtonElement;
                CustomGridDataCellElement cell = button.Parent as CustomGridDataCellElement;
     
                if (button.Tag != null)
                {
                    int idx = (int)button.Tag;
                    System.Diagnostics.Debug.Write("\n cell.Button" + idx.ToString());
                    switch (idx)
                    {
                        case 0:
                            break;
                        case 1:
                            break;
                        case 2:
                            break;
                    }
                }
            }

     

    Thanks

    Francisco

     

  7. Hristo
    Admin
    Hristo avatar
    716 posts

    Posted 18 Mar Link to this post

    Hello Francisco,

    Thank you for sharing your implementation.

    The solution is valid and it follows the suggestions made in our Creating Custom Cells documentation article.

    Please let me know if you need further assistance.

    Regards,
    Hristo Merdjanov
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
UI for WinForms is Visual Studio 2017 Ready