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

Problem with pinned column if there are custom GridDataCellElements.

11 Answers 285 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Raymond
Top achievements
Rank 1
Raymond asked on 19 Oct 2010, 10:16 AM

Hi!

 


VERSION: 2010 Q2 SP2

This is my simple application:

 


EditableCheckBoxCellElement:

 

  

namespace GridViewUnboundMode
{
    public class EditableCheckBoxCellElement : GridDataCellElement
    {
        private RadCheckBoxElement _chk;
        private RadTextBoxElement _txtBox;
  
        private CellValue _cellValue;
  
        public EditableCheckBoxCellElement(GridViewColumn column, GridRowElement row)
            : base(column, row)
        {
        }
  
        protected override void CreateChildElements()
        {
            base.CreateChildElements();
  
            _chk = new RadCheckBoxElement();
            _chk.Margin = new Padding(2, 2, 2, 2);
            _chk.MinSize = new Size(10, 10);
            _chk.Text = string.Empty;
            _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
            _chk.ToggleStateChanged += new StateChangedEventHandler(_chk_ToggleStateChanged);
  
            _txtBox = new RadTextBoxElement();
            _txtBox.Margin = new Padding(2, 2, 2, 2);
            _txtBox.MinSize = new Size(10, 10);
            _txtBox.Text = "sss";
  
            this.Children.Add(_chk);
            this.Children.Add(_txtBox);
        }
  
  
        void _chk_ToggleStateChanged(object sender, StateChangedEventArgs args)
        {
            if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.On)
            { _cellValue.IsAssigned = true; }
            else if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.Off)
            { _cellValue.IsAssigned = false; }
        }
  
        protected override SizeF ArrangeOverride(SizeF finalSize)
        {
            if (this.Children.Count == 2)
            {
                this.Children[0].Arrange(new RectangleF(2, 2, 10, 10));
                this.Children[1].Arrange(new RectangleF(21, 2, finalSize.Width - 28 - 10, 15));
            }
            return finalSize;
        }
  
        public override object Value
        {
            get { return _cellValue; }
            set
            {
                _cellValue = value as CellValue;
                if (_cellValue != null)
                {
                    _txtBox.Text = _cellValue.Text;
                    this.IsChecked = _cellValue.IsAssigned;
                }
            }
        }
  
        public bool IsChecked
        {
            get
            {
                return _cellValue.IsAssigned;
            }
            set
            {
                if (value)
                { _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.On; }
                else
                { _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off; }
                _cellValue.IsAssigned = value;
            }
        }
  
    }
}

EditableCheckBoxColumn:

 

 


namespace GridViewUnboundMode
{
    public class EditableCheckBoxColumn : GridViewDataColumn
    {
        public EditableCheckBoxColumn(): base()
        {
        }
   
        public override Type GetCellType(GridViewRowInfo row)
        {
            if (row is GridViewDataRowInfo)
            {
                return typeof(EditableCheckBoxCellElement);
            }        
            return base.GetCellType(row);
        }
    }
}

CellValue:

namespace GridViewUnboundMode
{
    public class CellValue
    {
        public string Text { get; set; }
        public bool IsAssigned { get; set; }
    }
}

Form1:

namespace GridViewUnboundMode
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            radGridView1.MultiSelect = true;
            radGridView1.AllowColumnChooser = false;
  
            GridViewDataColumn columnCSname = new GridViewTextBoxColumn();
            columnCSname.HeaderText = "Standard column";
            radGridView1.Columns.Add(columnCSname);
            columnCSname.Width = 160;
            columnCSname.ReadOnly = true;
  
            this.AddCustomColumns(4);
            this.AddNewRow();
            this.AddNewRow();
  
            columnCSname.IsPinned = true;
        }
  
        private void AddNewRow()
        {
            GridViewRowInfo rowInfo = this.radGridView1.Rows.AddNew();
            int columnIndex = 0;
            foreach (GridViewCellInfo cellInfo in rowInfo.Cells)
            {
                if (cellInfo.ColumnInfo.Index == 0)
                {
                    cellInfo.Value = string.Format("Standard column, Col: {0}, Row: {1}", cellInfo.ColumnInfo.Index, rowInfo.Index);
                }
                else
                {
                    CellValue cellValue = new CellValue();
                    cellValue.Text = string.Format("Col: {0}, Row: {1}", cellInfo.ColumnInfo.Index, rowInfo.Index);
  
                    cellInfo.Tag = cellValue;
                }
                columnIndex++;
            }
        }
  
        private void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
        {
            EditableCheckBoxCellElement cellElement = e.CellElement as EditableCheckBoxCellElement;
            if (cellElement != null)
            {
                CellValue val = e.CellElement.RowInfo.Cells[e.CellElement.ColumnIndex].Tag as CellValue;
                cellElement.Value = val;
            }
        }
  
        private void AddCustomColumns(int count)
        {
            for (int index = 0; index < count; index++)
            {
                GridViewDataColumn newColumn = new EditableCheckBoxColumn();
                newColumn.HeaderText = "Col" + (radGridView1.Columns.Count + 1).ToString();
                newColumn.Name = newColumn.HeaderText;
                newColumn.Width = 120;
                if (radGridView1.Columns.Count == 0)
                { newColumn.IsPinned = true; }
                radGridView1.Columns.Add(newColumn);
            }
        }
    }
}

 

 

 

 


When I run application I see form from attachment viewAfterStartup.JPG. “Standard column” is pinned at left.

 


FIRST PROBLEM

 

If I resize window to smaller size then I have scroll bar on the bottom.

When I start scrolling to right I have problem with text box from custom cells – it overlaps on “Standard column”. This is weird because this problem is only for text box, for check box it is ok (check box does not overlap pinned column) – please check attachments “scrollingCheckBox-OK.JPG” and “scrollingTextBox-NOTok.JPG”. What is wrong in my source code?

 



SECOND PROBLEM

 

When I unpin “Standard column” I see in this column cells of class EditableCheckBoxCellElement. How it is possible? Name of column is correct but cells change type. Check attachment “unpinnedFirstColumn.JPG”.

 



Regards

11 Answers, 1 is accepted

Sort by
0
Emanuel Varga
Top achievements
Rank 1
answered on 19 Oct 2010, 11:52 AM
Hello Raymond,

First of all, you are right about this, but i cannot consider this an issue, because the TextBoxElement in an input control it should be on top on other controls (usually).

That's why there is no column with a textbox in it, the textbox is just used as an editor, called on by the EditorRequired when the cell is in edit mode

I would suggest doing things in a different way, if possible, using just a a CheckBoxColumn with a custom editor, that will be able to change the Text for the current cell and also provide that check box element for changing the state. For more information about custom editors please check out this KB article.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Raymond
Top achievements
Rank 1
answered on 19 Oct 2010, 01:37 PM
FIRST PROBLEM - I will try your solution.

Do you have any ideas about SECOND PROBLEM?
0
Raymond
Top achievements
Rank 1
answered on 19 Oct 2010, 01:42 PM

Is there any property that controls behavior that check box is not visible and txt box is visible in my case?

0
Emanuel Varga
Top achievements
Rank 1
answered on 19 Oct 2010, 03:11 PM
Hello Raymond,

For the second problem, i found a custom cell provider to solve the problem, please take a look at this your example changed with a custom cell element provider:
namespace GridPinnedColumnTest
{
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Telerik.WinControls.UI;
 
    public partial class Form1 : Form
    {
        private RadGridView radGridView1;
 
        public Form1()
        {
            this.Controls.Add(radGridView1 = new RadGridView());
            radGridView1.Dock = DockStyle.Fill;
            InitializeComponent();
            radGridView1.MultiSelect = true;
            radGridView1.AllowColumnChooser = false;
 
            GridViewDataColumn columnCSname = new GridViewTextBoxColumn();
            radGridView1.TableElement.CellElementProvider = new CustomCellProvider(radGridView1.TableElement);
            columnCSname.HeaderText = "Standard column";
            radGridView1.Columns.Add(columnCSname);
            columnCSname.Width = 160;
            columnCSname.ReadOnly = true;
 
            this.AddCustomColumns(4);
            this.AddNewRow();
            this.AddNewRow();
 
            columnCSname.IsPinned = true;
        }
 
        private void AddNewRow()
        {
            GridViewRowInfo rowInfo = this.radGridView1.Rows.AddNew();
            int columnIndex = 0;
            foreach (GridViewCellInfo cellInfo in rowInfo.Cells)
            {
                if (cellInfo.ColumnInfo.Index == 0)
                {
                    cellInfo.Value = string.Format("Standard column, Col: {0}, Row: {1}", cellInfo.ColumnInfo.Index, rowInfo.Index);
                }
                else
                {
                    CellValue cellValue = new CellValue();
                    cellValue.Text = string.Format("Col: {0}, Row: {1}", cellInfo.ColumnInfo.Index, rowInfo.Index);
 
                    cellInfo.Tag = cellValue;
                }
 
                columnIndex++;
            }
        }
 
        private void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
        {
            EditableCheckBoxCellElement cellElement = e.CellElement as EditableCheckBoxCellElement;
            if (cellElement != null)
            {
                CellValue val = e.CellElement.RowInfo.Cells[e.CellElement.ColumnIndex].Tag as CellValue;
                cellElement.Value = val;
            }
        }
 
        private void AddCustomColumns(int count)
        {
            for (int index = 0; index < count; index++)
            {
                GridViewDataColumn newColumn = new EditableCheckBoxColumn();
                newColumn.HeaderText = "Col" + (radGridView1.Columns.Count + 1).ToString();
                newColumn.Name = newColumn.HeaderText;
                newColumn.Width = 120;
                if (radGridView1.Columns.Count == 0)
                {
                    newColumn.IsPinned = true;
                }
                radGridView1.Columns.Add(newColumn);
            }
        }
    }
 
    public class CustomCellProvider : CellElementProvider
    {
        public CustomCellProvider(GridTableElement tableElement)
            : base(tableElement)
        {
        }
 
        public override IVirtualizedElement<GridViewColumn> CreateElement(GridViewColumn data, object context)
        {
            var dataRow = context as GridDataRowElement;
            if (data.Name.StartsWith("Col") && dataRow != null)
            {
                return new EditableCheckBoxCellElement(data, dataRow);
            }
 
            return base.CreateElement(data, context);
        }
 
        public override bool IsCompatible(
            IVirtualizedElement<GridViewColumn> element, GridViewColumn data, object context)
        {
            if (data.Name.StartsWith("Col") &&
                context is GridDataRowElement)
            {
                return element is EditableCheckBoxCellElement;
            }
 
            if (element is EditableCheckBoxCellElement)
            {
                return false;
            }
 
            return base.IsCompatible(element, data, context);
        }
    }
 
    public class EditableCheckBoxCellElement : GridDataCellElement
    {
        private RadCheckBoxElement _chk;
        private RadTextBoxElement _txtBox;
 
        private CellValue _cellValue;
 
        public EditableCheckBoxCellElement(GridViewColumn column, GridRowElement row)
            : base(column, row)
        {
        }
 
        protected override void CreateChildElements()
        {
            base.CreateChildElements();
 
            _chk = new RadCheckBoxElement();
            _chk.Margin = new Padding(2, 2, 2, 2);
            _chk.MinSize = new Size(10, 10);
            _chk.Text = "sss";
            _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
            _chk.ToggleStateChanged += new StateChangedEventHandler(_chk_ToggleStateChanged);
 
            _txtBox = new RadTextBoxElement();
 
            _txtBox.Margin = new Padding(2, 2, 2, 2);
            _txtBox.MinSize = new Size(10, 10);
            _txtBox.Text = "asd";
 
            this.Children.Add(_chk);
            this.Children.Add(_txtBox);
        }
 
        void _chk_ToggleStateChanged(object sender, StateChangedEventArgs args)
        {
            if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.On)
            {
                _cellValue.IsAssigned = true;
            }
            else if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.Off)
            {
                _cellValue.IsAssigned = false;
            }
        }
 
        protected override SizeF ArrangeOverride(SizeF finalSize)
        {
            if (this.Children.Count == 2)
            {
                this.Children[0].Arrange(new RectangleF(2, 2, 10, 10));
                this.Children[1].Arrange(new RectangleF(21, 2, finalSize.Width - 28 - 10, 15));
            }
            return finalSize;
        }
 
        public override object Value
        {
            get
            {
                return _cellValue;
            }
            set
            {
                _cellValue = value as CellValue;
                if (_cellValue != null)
                {
                    _txtBox.Text = _cellValue.Text;
                    this.IsChecked = _cellValue.IsAssigned;
                }
            }
        }
 
        public bool IsChecked
        {
            get
            {
                return _cellValue.IsAssigned;
            }
            set
            {
                if (value)
                {
                    _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.On;
                }
                else
                {
                    _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
                }
                _cellValue.IsAssigned = value;
            }
        }
    }
 
    public class EditableCheckBoxColumn : GridViewDataColumn
    {
        public EditableCheckBoxColumn()
            : base()
        {
        }
 
        public override Type GetCellType(GridViewRowInfo row)
        {
            if (row is GridViewDataRowInfo)
            {
                return typeof(EditableCheckBoxCellElement);
            }
            return base.GetCellType(row);
        }
    }
 
    public class CellValue
    {
        public string Text
        {
            get;
            set;
        }
 
        public bool IsAssigned
        {
            get;
            set;
        }
    }
}

About the other problem, you can just use the Visibility property of the RadTextBoxElement to specify the state of that element, so an ElementVisibility of Collapse will hide the text box.

But again, if you will use a custom editor, you don't have to take care of this, you will just implement that cell that will edit, and like that article says on editor required, for that cell you specify the type of your editor.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Accepted
Alexander
Telerik team
answered on 22 Oct 2010, 12:20 PM
Hello Raymond,

I agree with Emanuel that the TextBoxElement is better to be used in a custom editor. It will help you to resolve the first issue.

The second issue appears, because of the column virtualization in RadGridView and reusing compatible cells from other columns. You can overcome it either by using a custom CellElementProvider, as suggested by Emanuel, or define the compatibility of the custom cell. The second approach in your initial solution is to override the IsCompatible method of the custom cell:
public override bool IsCompatible(GridViewColumn data, object context)
{
    return data is EditableCheckBoxColumn && context is GridDataRowElement;
}

I hope it helps. Please write back if you have further questions.

Best regards,
Alexander
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Raymond
Top achievements
Rank 1
answered on 29 Oct 2010, 02:38 PM
Hi

FIRST PROBLEM
I don`t know yet what I will do it this issue...

SECOND PROBLEM
Solution with bool IsCompatible(GridViewColumn data, object context) works perfect and I didn`t have to change to much my source code...

Regards
0
Raymond
Top achievements
Rank 1
answered on 04 Nov 2010, 03:32 PM

FIRST PROBLEM

I tried to use my own custom editor with checkbox and textbox but it is not enough good because if cell is not active and user clicks in checkbox checkbox state is not changed – because first click causes switching cell to edit mode - I couldn`t change this behavior.

 

So I tried another solution. When user clicks in label I change label to textbox – but I have problem because when text box becomes visible I cannot set focus on it. User must second time click in cell to have focus in textbox. This is my cell element.

Do you know how to set focus in textbox after textbox becomes visible?

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Telerik.WinControls.UI;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
  
namespace GridViewUnboundMode
{
    public class EditableCheckBoxCellElement : GridDataCellElement
    {
        private RadCheckBoxElement _chk;
        private RadTextBoxElement _txtBox;
        private RadLabelElement _lbl;
  
        private CellValue _cellValue;
  
        public EditableCheckBoxCellElement(GridViewColumn column, GridRowElement row)
            : base(column, row)
        { }
  
        protected override void CreateChildElements()
        {
            base.CreateChildElements();
  
            _chk = new RadCheckBoxElement();
            _chk.Margin = new Padding(2, 2, 2, 2);
            _chk.MinSize = new Size(10, 10);
            _chk.Text = string.Empty;
            _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off;
            _chk.ToggleStateChanged += new StateChangedEventHandler(_chk_ToggleStateChanged);
  
            _txtBox = new RadTextBoxElement();
            _txtBox.Margin = new Padding(2, 2, 2, 2);
            _txtBox.MinSize = new Size(10, 10);
  
            _lbl = new RadLabelElement();
            _lbl.Margin = new Padding(2, 2, 2, 2);
            _lbl.MinSize = new Size(10, 10);
            _lbl.MouseUp += new MouseEventHandler(_lbl_MouseUp);
  
  
            this.Children.Add(_chk);
            this.Children.Add(_txtBox);
            this.Children.Add(_lbl);
  
            _lbl.Visibility = Telerik.WinControls.ElementVisibility.Visible;
            _txtBox.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
        }
  
        void _lbl_MouseUp(object sender, MouseEventArgs e)
        {
            _lbl.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
            _txtBox.Visibility = Telerik.WinControls.ElementVisibility.Visible;
  
            //This doesn`t work:
            _txtBox.TextBoxItem.Focus();
            _txtBox.TextBoxItem.Select(0, 0);
        }
  
  
        void _chk_ToggleStateChanged(object sender, StateChangedEventArgs args)
        {
            if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.On)
            {
                _cellValue.IsAssigned = true;
            }
            else if (_chk.ToggleState == Telerik.WinControls.Enumerations.ToggleState.Off)
            { _cellValue.IsAssigned = false; }
        }
  
        protected override SizeF ArrangeOverride(SizeF finalSize)
        {
            if (this.Children.Count == 3)
            {
                this.Children[0].Arrange(new RectangleF(2, 2, 10, 10));
                this.Children[1].Arrange(new RectangleF(21, 2, finalSize.Width - 28 - 10, 15));
                this.Children[2].Arrange(new RectangleF(21, 2, finalSize.Width - 28 - 10, 15));
            }
            return finalSize;
        }
  
        public override object Value
        {
            get { return _cellValue; }
            set
            {
                _cellValue = value as CellValue;
                if (_cellValue != null)
                {
                    _txtBox.Text = _cellValue.Text;
                    _lbl.Text = _cellValue.Text;
                    this.IsChecked = _cellValue.IsAssigned;
                }
            }
        }
  
        public bool IsChecked
        {
            get
            {
                return _cellValue.IsAssigned;
            }
            set
            {
                if (value)
                { _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.On; }
                else
                { _chk.ToggleState = Telerik.WinControls.Enumerations.ToggleState.Off; }
                _cellValue.IsAssigned = value;
            }
        }
  
        public override bool IsCompatible(GridViewColumn data, object context)
        { return data is EditableCheckBoxColumn && context is GridDataRowElement; }
  
    }
}

Regards

 

 

0
Accepted
Alexander
Telerik team
answered on 05 Nov 2010, 10:09 AM
Hello Raymond,

You can focus the TextBoxElement by focusing its HostedControl:
_txtBox.TextBoxItem.HostedControl.Focus();

In your latest solution you can use the KeyDown and LostFocus events of the TextBox to update the cell value and to hide the TextBox after the edit is finished:
_txtBox.KeyDown += new KeyEventHandler(_txtBox_KeyDown);
_txtBox.TextBoxItem.LostFocus += new EventHandler(TextBoxItem_LostFocus);
 
private void _txtBox_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Enter)
    {
        _cellValue.Text = _txtBox.Text;
        _txtBox.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
        _lbl.Visibility = Telerik.WinControls.ElementVisibility.Visible;
        this.Focus();
    }
}
 
private void TextBoxItem_LostFocus(object sender, EventArgs e)
{
    _txtBox.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
    _lbl.Visibility = Telerik.WinControls.ElementVisibility.Visible;
}

Do not forget to unsubscribe from the events when the cell is disposed to prevent memory leaks:
protected override void DisposeManagedResources()
{
    _chk.ToggleStateChanged -= new StateChangedEventHandler(_chk_ToggleStateChanged);
    _txtBox.KeyDown -= new KeyEventHandler(_txtBox_KeyDown);
    _txtBox.TextBoxItem.LostFocus -= new EventHandler(TextBoxItem_LostFocus);
    _lbl.MouseUp -= new MouseEventHandler(_lbl_MouseUp);
    base.DisposeManagedResources();
}

I hope it helps. Please write back if you have more questions.

Best regards,
Alexander
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Raymond
Top achievements
Rank 1
answered on 05 Nov 2010, 12:25 PM
it works!
thank you very much

I have also another problem: My custom cells don`t have border lines. Why? How can I add border lines to my custom cells?

Regards
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 05 Nov 2010, 01:59 PM
Hello,

You just have to add this code to the custom cell for the theme to be applied on the cell, border and so on:
protected override Type ThemeEffectiveType
{
    get
    {
        return typeof(GridDataCellElement);
    }
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Raymond
Top achievements
Rank 1
answered on 05 Nov 2010, 03:26 PM
works fine
Tags
GridView
Asked by
Raymond
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
Raymond
Top achievements
Rank 1
Alexander
Telerik team
Share this question
or