This is a migrated thread and some comments may be shown as answers.

GridView are wrong to display child controls

6 Answers 115 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Paul
Top achievements
Rank 1
Paul asked on 03 May 2017, 03:23 AM

Hi,

I use GridView and custom cell element, however it is wrong to display, please help me to resolve it!

My code and video demo below
+ Change page size -> scroll -> change form size to normal -> hide to task bar -> re-open from task bar -> wrong

+ video: https://youtu.be/8ytr-AFMzRc
+ my code:

public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        public RadForm1()
        {
            InitializeComponent();
            this.ThemeName = "TelerikMetro";
            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
 
            var layer1 = new TableLayoutPanel();
 
            layer1.Dock = DockStyle.Fill;
            layer1.Location = new Point(0);
            layer1.Margin = new Padding(0);
            layer1.ColumnCount = 2;
            layer1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 30F));
            layer1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
            layer1.RowCount = 2;
            layer1.RowStyles.Add(new RowStyle(SizeType.Absolute, 28F));
            layer1.RowStyles.Add(new RowStyle(SizeType.Absolute, 0F));
            layer1.AutoSize = true;
 
            var label = new RadLabel();
            label.Dock = DockStyle.Fill;
            label.Text = @"Test grid view";
            label.ThemeName = "TelerikMetro";
 
            layer1.Controls.Add(label, 0, 0);
            layer1.SetColumnSpan(label, 2);
 
            var radGridView1 = new RadGridView
            {
                Dock = DockStyle.Fill,
                AutoGenerateColumns = false,
                AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill,
                ThemeName = "TelerikMetroTouch",
                AllowDeleteRow = false,
                AllowAddNewRow = false,
                // AllowEditRow = false,
                EnableGrouping = false,
                EnablePaging = true,
                Margin = new Padding(5, 10, 5, 10),
                PageSize = 10,
                AllowColumnHeaderContextMenu = false,
                AllowRowHeaderContextMenu = false
            };
 
            radGridView1.CreateCell += RadGridView1_CreateCell;
 
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 1", "Column 1")
            {
                HeaderText = @"",
                ReadOnly = true,
                Width = 280,
                AllowSort = false,
                AllowResize =  false,
                AllowReorder = false
            });
 
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 2", "Column 2"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 3", "Column 3"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 4", "Column 4"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 5", "Column 5"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 6", "Column 6"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 7", "Column 7"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 8", "Column 8"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 9", "Column 9"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 10", "Column 10"));
            radGridView1.Columns.Add(new GridViewMaskBoxColumn("col 11", "Column 11"));
 
            RenderData(radGridView1);
 
            GridViewUpdateHeight(radGridView1);
 
            var layer2 = new TableLayoutPanel();
 
            layer2.Dock = DockStyle.Fill;
            layer2.Location = new Point(0);
            layer2.Margin = new Padding(0);
            layer2.ColumnCount = 1;
            layer2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
            layer2.RowCount = 1;
            layer2.RowStyles.Add(new RowStyle(SizeType.Absolute, radGridView1.Height));
            layer2.AutoSize = true;
 
            layer2.Controls.Add(radGridView1, 0, 0);
 
            layer1.Controls.Add(layer2, 1, 1);
            layer1.RowStyles[1].SizeType = SizeType.AutoSize;
 
            Controls.Add(layer1);
        }
 
        private void GridViewUpdateHeight(RadGridView grid)
        {
            var actualRowCount = grid.RowCount < grid.PageSize ? grid.RowCount : grid.PageSize;
            var height = actualRowCount * 40;
 
            if (grid.AllowAddNewRow && !grid.ReadOnly)
            {
                height += grid.MasterView.TableAddNewRow.GetActualHeight(grid.TableElement);
            }
            if (grid.EnableFiltering)
            {
                height += grid.MasterView.TableFilteringRow.GetActualHeight(grid.TableElement);
            }
            if (grid.ShowColumnHeaders)
            {
                height += grid.MasterView.TableHeaderRow.GetActualHeight(grid.TableElement);
            }
            if (grid.EnablePaging)
            {
                height += 50;
            }
            height += 20; // horizontal scroll bar height
 
            grid.Height = height;
        }
 
        private void RenderData(RadGridView radGridView1)
        {
            for (int k = 0; k < 100; k++)
            {
                GridViewDataRowInfo rowInfo = new GridViewDataRowInfo(radGridView1.MasterView);
                rowInfo.Height = 40;
 
                for (int i = 1; i < radGridView1.Columns.Count; i++)
                {
                    rowInfo.Cells[i].Value = "Row: " + k + " - column: " + i;
                }
 
                radGridView1.Rows.Add(rowInfo);
            }
        }
 
        private void RadGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
        {
            if (e.Row is GridFilterRowElement)
                return;
 
            if (e.Column.Index == 0)
            {
                if (e.Row is GridTableHeaderRowElement && e.CellType == typeof(GridHeaderCellElement))
                {
                    e.CellElement = new PageSizeDropdownHeaderCellElement(e.Column, e.Row);
                }
 
                if (e.Row is GridDataRowElement)
                {
                    var actionCellElement = new ActionCellElement(e.Column, e.Row);
                    e.CellElement = actionCellElement;
                }
            }
        }
    }
 
    public sealed class PageSizeDropdownHeaderCellElement : GridHeaderCellElement
    {
        public PageSizeDropdownHeaderCellElement(GridViewColumn col, GridRowElement row) : base(col, row)
        {
            TextAlignment = ContentAlignment.TopCenter;
            Alignment = ContentAlignment.TopCenter;
            AutoSizeMode = RadAutoSizeMode.FitToAvailableSize;
        }
 
        private RadDropDownListElement _dropDownListElement;
 
        protected override void CreateChildElements()
        {
            base.CreateChildElements();
            if (_dropDownListElement?.DataSource == null)
            {
                _dropDownListElement = new RadDropDownListElement();
                _dropDownListElement.BindingContext = new BindingContext();
                _dropDownListElement.DropDownStyle = Telerik.WinControls.RadDropDownStyle.DropDownList;
 
                _dropDownListElement.Items.Clear();
                _dropDownListElement.Items.Add(new RadListDataItem("10", 10) { Selected = true });
                _dropDownListElement.Items.Add(new RadListDataItem("25", 25));
                _dropDownListElement.Items.Add(new RadListDataItem("50", 50));
                _dropDownListElement.Items.Add(new RadListDataItem("100", 100));
                _dropDownListElement.Items.Add(new RadListDataItem("All", -1));
 
                _dropDownListElement.Margin = new Padding(15, 0, 0, 0);
                _dropDownListElement.StretchHorizontally = true;
                _dropDownListElement.NotifyParentOnMouseInput = false;
                _dropDownListElement.Popup.MouseClick -= Popup_MouseClick;
                _dropDownListElement.Popup.MouseClick += Popup_MouseClick;
 
                _dropDownListElement.PopupClosed -= _dropDownListElement_PopupClosed;
                _dropDownListElement.PopupClosed += _dropDownListElement_PopupClosed;
 
                _dropDownListElement.FitToSizeMode = RadFitToSizeMode.FitToParentPadding;
                _dropDownListElement.AutoSizeMode = RadAutoSizeMode.FitToAvailableSize;
                _dropDownListElement.AutoSize = true;
 
                this.Children.Add(_dropDownListElement);
            }
        }
 
        private RadListVisualItem _elementUnderMouse;
 
        private void Popup_MouseClick(object sender, MouseEventArgs e)
        {
            _elementUnderMouse = _dropDownListElement.Popup.ElementTree.GetElementAtPoint(e.Location) as RadListVisualItem;
        }
 
        private void _dropDownListElement_PopupClosed(object sender, RadPopupClosedEventArgs args)
        {
            if (_elementUnderMouse == null)
            {
                return;
            }
            if (_dropDownListElement.SelectedIndex == -1)
                return;
 
            var pageSize = Convert.ToInt32(_elementUnderMouse.Data.Value);
 
            if (pageSize == -1)
            {
                pageSize = GridControl.RowCount < 1000 ? 1000 : GridControl.RowCount;
            }
 
            // Backup selected pageSize and re-select when re-render grid view
            RowInfo.Tag = pageSize;
 
            GridControl.PageSize = pageSize;
            _elementUnderMouse = null;
        }
 
        protected override void SetContentCore(object value)
        {
            if (_dropDownListElement != null && RowInfo?.Tag != null)
            {
                this._dropDownListElement.SelectedValue = (int)RowInfo.Tag;
            }
        }
 
        public override bool IsCompatible(GridViewColumn data, object context)
        {
            return context is GridTableHeaderRowElement;
        }
 
        protected override Type ThemeEffectiveType => typeof(GridHeaderCellElement);
    }
 
    public sealed class ActionCellElement : GridDataCellElement
    {
        #region Public Delegates
 
        public delegate void EventHandler(object sender, EventArgs e);
 
        #endregion Public Delegates
 
        #region Public Events
 
        public event EventHandler OnSelectedRecord;
 
        public event EventHandler OnUnSelectedRecord;
 
        #endregion Public Events
 
        #region Private Fields
 
        public GridViewCheckBoxElement CheckBoxElement;
        public RadButtonElement BtnFlag;
        public RadButtonElement BtnTimeCircle;
 
        #endregion Private Fields
 
        private readonly RadOffice2007ScreenTipElement _screenTip;
 
        #region Public Constructors
 
        public ActionCellElement(GridViewColumn column, GridRowElement row) : base(column, row)
        {
            Name = "ActionCell_" + RowIndex;
            Text = string.Empty;
 
            _screenTip = new RadOffice2007ScreenTipElement();
            _screenTip.MainTextLabel.Padding = new Padding(2);
            _screenTip.CaptionLabel.Padding = new Padding(2);
            _screenTip.CaptionLabel.Text = @"<html><color=red>Created Date";
            BtnTimeCircle.ScreenTip = _screenTip;
        }
 
        #endregion Public Constructors
 
        public void SetFlagImage(GridViewRowInfo rowInfo = null)
        {
            if (rowInfo != null)
            {
                RowInfo = rowInfo;
            }
        }
 
        #region Protected Methods
 
        protected override SizeF ArrangeOverride(SizeF finalSize)
        {
            SizeF size = base.ArrangeOverride(finalSize);
            RectangleF clientRect = GetClientRectangle(finalSize);
            float marginX = 4;
            float width = clientRect.Width - (Children.Count + 1) * 4;
            foreach (RadElement element in this.Children)
            {
                var btnWidth = width / Children.Count;
                element.Arrange(new RectangleF(
                        marginX,
                        clientRect.Top + 2,
                        btnWidth,
                        clientRect.Height - 4));
                marginX += btnWidth + 4;
            }
            return size;
        }
 
        protected override void CreateChildElements()
        {
            BtnFlag = new GridViewButtonElement(GetChildElementName("btnFlag"), Resources.USDA_icon_RedFlag);
 
            BtnTimeCircle = new GridViewButtonElement(GetChildElementName("btnTimeCircle"), Resources.USDA_icon_TimeCircle);
 
            CheckBoxElement = new GridViewCheckBoxElement(GetChildElementName("chkBoxItem"));
            CheckBoxElement.ToggleState = ToggleState.Off;
 
            CheckBoxElement.AutoSizeMode = RadAutoSizeMode.FitToAvailableSize;
            BtnTimeCircle.AutoSizeMode = RadAutoSizeMode.FitToAvailableSize;
            BtnFlag.AutoSizeMode = RadAutoSizeMode.FitToAvailableSize;
 
            Children.Clear();
            Children.Add(CheckBoxElement);
            Children.Add(BtnFlag);
            Children.Add(BtnTimeCircle);
        }
 
        #endregion Protected Methods
 
        #region Private Methods
        private string GetChildElementName(string elementName)
        {
            return elementName;
        }
 
        #endregion Private Methods
    }
 
    public sealed class GridViewCheckBoxElement : RadCheckBoxElement
    {
        public bool MultiSelect { get; set; }
 
        public GridViewCheckBoxElement(string name, string text = null)
        {
            DisplayStyle = DisplayStyle.Text;
            Name = name;
            Text = text;
            Alignment = ContentAlignment.MiddleCenter;
            ShowBorder = false;
            BackColor = Color.White;
            CheckAlignment = ContentAlignment.MiddleCenter;
            TextAlignment = ContentAlignment.MiddleCenter;
            MultiSelect = false;
        }
    }
 
    public sealed class GridViewButtonElement : RadButtonElement
    {
        public GridViewButtonElement(string name, Image image = null, string text = null)
        {
            if (image != null)
            {
                Image = ResizeImage(image, 25, 25);
                ImageAlignment = ContentAlignment.MiddleCenter;
            }
 
            DisplayStyle = image != null && string.IsNullOrWhiteSpace(text)
                ? DisplayStyle.ImageAndText
                : image != null
                    ? DisplayStyle.Image
                    : DisplayStyle.Text;
 
            Name = name;
            Text = text;
            Alignment = ContentAlignment.MiddleCenter;
            ShowBorder = false;
            BackColor = Color.White;
        }
 
        private Bitmap ResizeImage(Image image, int width, int height)
        {
            var destRect = new Rectangle(0, 0, width, height);
            var destImage = new Bitmap(width, height);
 
            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
 
            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
 
                using (var wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }
 
            return destImage;
        }
    }

Thanks,

Paul.

6 Answers, 1 is accepted

Sort by
0
Accepted
Dimitar
Telerik team
answered on 03 May 2017, 06:34 AM
Hi Paul,

Thank you for writing.

In this case, you should create a custom column instead of using the CreateRow event. I have attached an example that shows this approach. In addition, I have overridden the IsCompatible method and the ThemeEffectiveType property.

I hope this will be useful. Let me know if you have additional questions.

Regards,
Dimitar
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Paul
Top achievements
Rank 1
answered on 03 May 2017, 11:53 AM

Hi Dimitar,

Thank for your helping,

In your example, i want to add more events for "ActionCellElement" like the picture below, there events will be invoke from "ActionCellElement", what i need to do?

Thanks,

Paul.

0
Accepted
Dimitar
Telerik team
answered on 03 May 2017, 12:58 PM
Hi Paul,

You can add the events to the custom column class:
public class CustomColumn : GridViewDataColumn
{
    public CustomColumn(string fieldName) : base(fieldName, fieldName)
    {
    }
    public event EventHandler MyEvent;
 
    public void OnMyEvent(EventArgs e)
    {
        if (MyEvent != null)
        {
            MyEvent(this, e);
        }
    }
    public override Type GetCellType(GridViewRowInfo row)
    {
        if (row is GridViewDataRowInfo)
        {
            return typeof(ActionCellElement);
        }
        return base.GetCellType(row);
    }
}

Then raise them from the cell element:
//ActionCellElement class
private void BtnTimeCircle_Click(object sender, EventArgs e)
{
    var col = this.ColumnInfo as CustomColumn;
    col.OnMyEvent(new EventArgs());
}

Should you have any other questions do not hesitate to ask.

Regards,
Dimitar
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Paul
Top achievements
Rank 1
answered on 04 May 2017, 03:04 AM

Hi Dimitar,

Thank for your helped, this issue was resolved!

Thanks,
Paul

0
Paul
Top achievements
Rank 1
answered on 05 May 2017, 03:37 AM

Hi Dimitar,

I want to know when cell element created, because i need passing some data into cell element and execute some functions from cell. What i need to do?

Thanks,
Paul

0
Dimitar
Telerik team
answered on 09 May 2017, 10:16 AM
Hi Paul,

The grid is using UI Virtualization which means that cell elements are created only for the currently visible cells. This is why the elements are not suitable for storing any data. This can be achieved by using the Tag property of each cell (GridViewCellInfo).

First, you can set it when adding the rows: 
GridViewDataRowInfo rowInfo = new GridViewDataRowInfo(radGridView1.MasterView);
rowInfo.Height = 40;
rowInfo.Cells[0].Tag = "Test " + k;

Then you can use it when the cell element is attached to the grid:
public override void Attach(GridViewColumn data, object context)
{
    base.Attach(data, context);
    if (this.RowInfo.Cells[this.ColumnInfo.Name].Tag == null)
    {
        return;
    }
  
    this.BtnFlag.Text = this.RowInfo.Cells[this.ColumnInfo.Name].Tag.ToString();
}

Please let me know if there is something else I can help you with. 
 
Regards,
Dimitar
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
GridView
Asked by
Paul
Top achievements
Rank 1
Answers by
Dimitar
Telerik team
Paul
Top achievements
Rank 1
Share this question
or