To reproduce: BindingList<Item> items = new BindingList<Item>(); public Form1() { InitializeComponent(); for (int i = 0; i < 5; i++) { items.Add(new Item(i,i * 1.25m)); } this.radGridView1.DataSource = items; this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; GridViewSummaryItem summaryItem = new GridViewSummaryItem(); summaryItem.Name = "Price"; summaryItem.Aggregate = GridAggregateFunction.Sum; GridViewSummaryRowItem summaryRowItem = new GridViewSummaryRowItem(); summaryRowItem.Add(summaryItem); this.radGridView1.SummaryRowsTop.Add(summaryRowItem); this.timer1.Start(); } public class Item { private int id; private decimal price; public Item(int id, decimal price) { this.id = id; this.price = price; } public int Id { get { return this.id; } set { this.id = value; } } public decimal Price { get { return this.price; } set { this.price = value; } } } private void timer1_Tick(object sender, EventArgs e) { items[0].Price += 1; this.radGridView1.Rows[0].InvalidateRow(); this.radGridView1.MasterView.SummaryRows[0].InvalidateRow(); } Workaround: refresh the MasterTemplate or implement the INotifyPropertyChanged
To reproduce: public Form1() { InitializeComponent(); for (int i = 0; i < 10; i++) { this.radGridView1.Columns.Add("Col"+i); } this.radGridView1.TableElement.RowDragHint = null; } Workaround: public Form1() { InitializeComponent(); for (int i = 0; i < 10; i++) { this.radGridView1.Columns.Add("Col"+i); } this.radGridView1.TableElement.RowDragHint = null; CustomRadGridViewDragDropService service = new CustomRadGridViewDragDropService(this.radGridView1.GridViewElement); this.radGridView1.GridViewElement.RegisterService(service); } public class CustomRadGridViewDragDropService : RadGridViewDragDropService { public CustomRadGridViewDragDropService(RadGridViewElement gridViewElement) : base(gridViewElement) { } public override string Name { get { return typeof(RadGridViewDragDropService).Name; } } protected override void PrepareDragHint(ISupportDrop dropTarget) { if (this.GridViewElement.TableElement.RowDragHint == null) { return; } base.PrepareDragHint(dropTarget); } protected override IGridDragDropBehavior GetDragDropBehavior() { IGridDragDropBehavior behavior = null; ISupportDrop dropTarget = this.DropTarget; if (dropTarget is GridHeaderCellElement) { behavior = new CustomGridColumnDragDropBehvavior(); return behavior; } return base.GetDragDropBehavior(); } } public class CustomGridColumnDragDropBehvavior : GridColumnDragDropBehvavior { public override Size GetDragHintSize(ISupportDrop dropTarget) { if (this.DragHint==null) { return new Size(0, 0); } return base.GetDragHintSize(dropTarget); } }
To reproduce: public Form1() { InitializeComponent(); DataTable dt = new DataTable(); for (int i = 0; i < 10; i++) { dt.Columns.Add("Col" + i); } for (int i = 0; i < 10; i++) { DataRow row = dt.NewRow(); foreach (DataColumn col in dt.Columns) { row[col.ColumnName] = "Data " + i + "." + dt.Columns.IndexOf(col); } dt.Rows.Add(row); } this.radGridView1.DataSource = dt; this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Bottom; this.radGridView1.Columns[9].IsVisible = false; this.radGridView1.Columns[8].ReadOnly = true; this.radGridView1.Columns[2].IsVisible = false; this.radGridView1.Columns[4].IsVisible = false; this.radGridView1.Columns[6].IsVisible = false; } Workaround: use a custom row behavior and control what to be the selected cell when pressing the Tab key for example: public Form1() { InitializeComponent(); DataTable dt = new DataTable(); for (int i = 0; i < 10; i++) { dt.Columns.Add("Col" + i); } for (int i = 0; i < 10; i++) { DataRow row = dt.NewRow(); foreach (DataColumn col in dt.Columns) { row[col.ColumnName] = "Data " + i + "." + dt.Columns.IndexOf(col); } dt.Rows.Add(row); } this.radGridView1.DataSource = dt; this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Bottom; this.radGridView1.Columns[9].IsVisible = false; this.radGridView1.Columns[8].ReadOnly = true; this.radGridView1.Columns[2].IsVisible = false; this.radGridView1.Columns[4].IsVisible = false; this.radGridView1.Columns[6].IsVisible = false; //register the custom row behavior BaseGridBehavior gridBehavior = radGridView1.GridBehavior as BaseGridBehavior; gridBehavior.UnregisterBehavior(typeof(GridViewNewRowInfo)); gridBehavior.RegisterBehavior(typeof(GridViewNewRowInfo), new CustomGridHierarchyRowBehavior()); } public class CustomGridHierarchyRowBehavior : GridNewRowBehavior { protected override bool ProcessTabKey(KeyEventArgs keys) { bool isLastColumn = this.Navigator.IsLastColumn(this.GridControl.CurrentColumn); bool result = base.ProcessTabKey(keys); if (isLastColumn) { this.GridControl.CurrentColumn = this.GridControl.Columns[0]; this.GridControl.BeginEdit(); } return result; } }
To reproduce: - Add some columns to a grid and make one read-only. - Add a value to the new row then click the read-only cell. - Click outside of the grid (focus another control). - The new row is not added. Workaround: radgridView1.EndEdit() radgridView1.MasterView.TableAddNewRow.EndAddNewRow()
To reproduce: - Sort the grid and then reset the data source. - Format the rows like this: void radGridView1_RowFormatting(object sender, Telerik.WinControls.UI.RowFormattingEventArgs e) { string exception_status = ""; string completed_user = ""; if (!DBNull.Value.Equals(e.RowElement.RowInfo.Cells["Name"].Value)) { exception_status = e.RowElement.RowInfo.Cells["Name"].Value.ToString(); } if (!DBNull.Value.Equals(e.RowElement.RowInfo.Cells["Drug"].Value)) { completed_user = e.RowElement.RowInfo.Cells["Drug"].Value.ToString().Trim(); } if (exception_status == "Sam" && completed_user == "Enebrel") { e.RowElement.ForeColor = Color.Red; } else { e.RowElement.ForeColor = Color.Black; } } Workaround: if (e.RowElement.RowInfo.Cells.Count ==0) { return; }
To reproduce: use the attached sample project Workaround: refresh the template when updating the data source: this.radGridView1.MasterTemplate.Refresh();
Workaround: public Form1() { InitializeComponent(); this.radGridView1.TableElement.VScrollBar.ValueChanged += VScrollBar_ValueChanged; } private void VScrollBar_ValueChanged(object sender, EventArgs e) { int maxValue = this.radGridView1.TableElement.VScrollBar.Maximum - this.radGridView1.TableElement.VScrollBar.LargeChange; if (maxValue < 0) { this.radGridView1.TableElement.VScrollBar.Value = 0; } else if (this.radGridView1.TableElement.VScrollBar.Value > maxValue) { this.radGridView1.TableElement.VScrollBar.Value = maxValue; } }
To reproduce: - Add 100000 rows to the grid. - Filter the grid so there are no rows. - Call the BestFitColumns method: radGridView1.MasterTemplate.BestFitColumns(Telerik.WinControls.UI.BestFitColumnMode.DisplayedCells) Workaround: If gridview.MasterTemplate.DataView.Count > 0 Then gridview.MasterTemplate.BestFitColumns() End If
To reproduce: public partial class Form1 : Form { public Form1() { InitializeComponent(); var data = new List<Thing>(); this.radGridView1.DataSource = data ; this.radGridView1.DataError += RadGridView1_DataError; } private void RadGridView1_DataError(object sender, Telerik.WinControls.UI.GridViewDataErrorEventArgs e) { } public class Thing { private Thing() { } } }
Please refer to the attached gif file. Workaround: specify the MinimumSize property of the grid and its parent container to have a greater width than the DesiredSize of the group panel.
To reproduce: - Add date time column to a grid and set the MaskType to FreeFormDateTime (this can be done by accessing the editor in the CellEditorInitialized event). - Type a year in the editor and click the right arrow key until the cell is changed. Workaround: class MyRadDateTimeEditor : RadDateTimeEditor { bool isRightmostMaskItemSelected = false; public override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.Right) { FreeFormDateTimeProvider provider = ((RadDateTimeEditorElement) this.EditorElement).TextBoxElement.Provider as FreeFormDateTimeProvider; if (provider.TextBoxItem.SelectionStart == provider.TextBoxItem.Text.Length) { this.isRightmostMaskItemSelected = true; } } else { base.OnKeyDown(e); } } protected override void OnKeyUp(KeyEventArgs e) { if (e.KeyCode == Keys.Right) { if (isRightmostMaskItemSelected) { isRightmostMaskItemSelected = false; GridDateTimeCellElement cell = this.OwnerElement as GridDateTimeCellElement; cell.GridControl.EndEdit(); } } else { base.OnKeyUp(e); } } } void radGridView1_CellEditorInitialized(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e) { RadDateTimeEditor editor = e.ActiveEditor as RadDateTimeEditor; if (editor != null) { var editorElement = editor.EditorElement as RadDateTimeEditorElement; editorElement.TextBoxElement.MaskType = MaskType.FreeFormDateTime; } }
To reproduce: public Form1() { InitializeComponent(); List<Item> items = new List<Item>(); items.Add(new Item(1,"sample")); items.Add(new Item(2, null)); items.Add(new Item(3, "sample2")); this.radGridView1.DataSource = items; this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.EnableFiltering = true; this.radGridView1.ShowFilteringRow = false; this.radGridView1.ShowHeaderCellButtons = true; } public class Item { public int Id { get; set; } public string Description { get; set; } public Item(int id, string description) { this.Id = id; this.Description = description; } } Workaround: If possible, instead of using null value, use empty string. If not possible, you will have to employ 3 classes - MyFilterMenuTreeElement, MyFilterMenuTreeItem, MyListFilterPopup. The classes are provided in the attached project RadGridViewFiltering.zip. Once you add the classes to your project, all you have to do is to replace the default popup with the new one, in the FilterPopupRequired handler: private void RadGridView1_FilterPopupRequired(object sender, FilterPopupRequiredEventArgs e) { if (e.FilterPopup is RadListFilterPopup) { e.FilterPopup = new MyListFilterPopup(e.Column); } } The approach is also demonstrated in the attached project.
Note: as a result ArgumentException is thrown when accessing a cell value. To reproduce: private DataTable dt; private GridViewRowInfo selectedRow; public Form1() { InitializeComponent(); PopulateGrid(); PopulateGrid(); } private void PopulateGrid() { dt = new DataTable(); dt.Columns.Add("Version No", typeof(Int32)); DataRow dr = dt.NewRow(); dr["Version No"] = 2385; dt.Rows.Add(dr); this.radGridView1.DataSource = dt; MessageBox.Show(selectedRow.Cells[0].ColumnInfo.Name); MessageBox.Show(selectedRow.Cells[0].Value.ToString()); //This will error on the second time through } private void radGridView1_CurrentRowChanged(object sender, CurrentRowChangedEventArgs e) { //This event is not firing on the second population of the grid in the new Telerik version. //In the old version, it did if (!this.radGridView1.CurrentRow.IsSystem && !this.radGridView1.CurrentRow.HasChildRows() && this.radGridView1.CurrentRow.Cells.Count > 0) selectedRow = this.radGridView1.CurrentRow; } Workaround: use the RadGridView.CurrentRow property directly when accessing the cell value.
Work around: create a custom GridCheckBoxHeaderCellElement and override the SetCheckBoxState method public class MyGridCheckBoxHeaderCellElement : GridCheckBoxHeaderCellElement { public MyGridCheckBoxHeaderCellElement(GridViewColumn column, GridRowElement row) : base(column, row) { } protected override Type ThemeEffectiveType { get { return typeof(GridHeaderCellElement); } } protected override bool SetCheckBoxState() { bool foundNonCheckedRows = false; foreach (GridViewRowInfo row in this.ViewInfo.Rows) { foundNonCheckedRows = this.CheckCheckBoxValueForAllRows(row, foundNonCheckedRows); if (foundNonCheckedRows) { SetCheckBoxState(ToggleState.Off); break; } } if (!foundNonCheckedRows && this.ViewInfo.Rows.Count > 0) //we must have at least one row in order to check the header cell { SetCheckBoxState(ToggleState.On); } return foundNonCheckedRows; } private bool CheckCheckBoxValueForAllRows(GridViewRowInfo row, bool foundNonCheckedRows) { GridViewChildRowCollection currentRowColection; if (foundNonCheckedRows) { return foundNonCheckedRows; } if (row.HasChildRows()) { currentRowColection = row.ChildRows; } else { currentRowColection = row.ViewInfo.Rows; } foreach (GridViewRowInfo rowInfo in currentRowColection) { GridViewGroupRowInfo groupInfo = rowInfo as GridViewGroupRowInfo; if (groupInfo != null) { foundNonCheckedRows = this.CheckCheckBoxValueForAllRows(groupInfo, foundNonCheckedRows); } else { object cellValue = rowInfo.Cells[this.ColumnIndex].Value; bool? valueFromColumnTypeConvertor = null; if (this.ColumnInfo is GridViewDataColumn) { TypeConverter convertor = ((GridViewDataColumn)this.ColumnInfo).DataTypeConverter; if (convertor != null && (convertor.CanConvertTo(typeof(bool)) || convertor.CanConvertTo(typeof(ToggleState)))) { try { valueFromColumnTypeConvertor = Convert.ToBoolean(convertor.ConvertTo(cellValue, typeof(bool))); } catch (FormatException)//convert to bool fails { } catch (NotSupportedException)//coverting NULL { } } } try { if (rowInfo != this.RowInfo && (cellValue == null || cellValue == DBNull.Value) || (valueFromColumnTypeConvertor.HasValue && !valueFromColumnTypeConvertor.Value) || (!valueFromColumnTypeConvertor.HasValue && !Convert.ToBoolean(cellValue))) { foundNonCheckedRows = true; } } catch (FormatException)//convert to bool fails { } } } return foundNonCheckedRows; } }
FIX. RadGridView - exception when binding to entities collection and specifying DataMember under Windows XP
To reproduce: use the following code snippet and try to delete a child row: public Form1() { InitializeComponent(); DataTable dt = new DataTable(); dt.Columns.Add("Id", typeof(int)); dt.Columns.Add("ParentId", typeof(int)); dt.Columns.Add("Name", typeof(string)); for (int i = 0; i < 5; i++) { dt.Rows.Add(i, null, "Item" + i); } Random rand = new Random(); for (int i = 5; i < 30; i++) { dt.Rows.Add(i, rand.Next(0, 5), "Child item" + i); } this.radGridView1.Relations.AddSelfReference(this.radGridView1.MasterTemplate, "Id", "ParentId"); this.radGridView1.DataSource = dt; this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.UserDeletingRow += radGridView1_UserDeletingRow; } private void radGridView1_UserDeletingRow(object sender, Telerik.WinControls.UI.GridViewRowCancelEventArgs e) { if (this.radGridView1.CurrentRow.HasChildRows()) { DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete this row?", "Delete Row confirmation", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.No) { e.Cancel = true; } } } Workaround: use the RadGridView.CurrentRow.ChildRows.Count property.
Please refer to the attached sample project. Workaround: public class MyGridCheckBoxCellElement : GridCheckBoxCellElement { public MyGridCheckBoxCellElement(GridViewColumn column, GridRowElement row) : base(column, row) { } protected override Type ThemeEffectiveType { get { return typeof(GridCheckBoxCellElement); } } public override bool IsCompatible(GridViewColumn data, object context) { GridViewCheckBoxColumn col = data as GridViewCheckBoxColumn; if (col != null) { return col.ThreeState == ((RadCheckBoxEditor)this.Editor).ThreeState; } return base.IsCompatible(data, context); } } private void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e) { if (e.CellType == typeof(GridCheckBoxCellElement)) { e.CellElement = new MyGridCheckBoxCellElement(e.Column, e.Row); } }
To reproduce: -Create a new ColumnGroupsViewDefinition and pin the first group. - Asign the view to the grid. Workaround: Pin the group after the view is asigned.
How to reproduce: public partial class Form1 : Form { public Form1() { InitializeComponent(); this.radGridView1.DataSource = this.GetData(); this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; this.radGridView1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; foreach (var col in this.radGridView1.Columns) { col.HeaderTextAlignment = ContentAlignment.MiddleLeft; } } private DataTable GetData() { DataTable dt = new DataTable(); dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Date", typeof(DateTime)); dt.Columns.Add("Bool", typeof(bool)); dt.Columns.Add("Bool1", typeof(bool)); dt.Columns.Add("Bool2", typeof(bool)); for (int i = 0; i < 50; i++) { dt.Rows.Add("Name " + i, DateTime.Now.AddMinutes(i), i % 2 == 0 ? true : false, false, false); } return dt; } private void radButton1_Click(object sender, EventArgs e) { this.radGridView1.PrintPreview(); } } Workaround: public partial class Form1 : Form { public Form1() { InitializeComponent(); this.radGridView1.DataSource = this.GetData(); this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; this.radGridView1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; this.radGridView1.PrintCellFormatting += radGridView1_PrintCellFormatting; foreach (var col in this.radGridView1.Columns) { col.HeaderTextAlignment = ContentAlignment.MiddleLeft; } } private void radGridView1_PrintCellFormatting(object sender, PrintCellFormattingEventArgs e) { if (e.Row is GridViewTableHeaderRowInfo && this.radGridView1.RightToLeft == System.Windows.Forms.RightToLeft.Yes) { e.PrintCell.TextAlignment = ContentAlignment.MiddleRight; } } private DataTable GetData() { DataTable dt = new DataTable(); dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Date", typeof(DateTime)); dt.Columns.Add("Bool", typeof(bool)); dt.Columns.Add("Bool1", typeof(bool)); dt.Columns.Add("Bool2", typeof(bool)); for (int i = 0; i < 50; i++) { dt.Rows.Add("Name " + i, DateTime.Now.AddMinutes(i), i % 2 == 0 ? true : false, false, false); } return dt; } private void radButton1_Click(object sender, EventArgs e) { this.radGridView1.PrintPreview(); } }