The group summary rows are not updated correctly when a data row is moved from one group to another.
If two conditional formatting objects apply to the same cell and the cell meets both conditions, the settings from both of them should apply to the cell (if they do not apply to the same property).
The issue appears when the current column of the control is changed programmatically in a way that the RadGridView's horizontal scrollbar value needs to be positioned between its minimum and maximum value.
The vertical scrollbar of RadGridView is not correctly calculated in a scenario with AutoSizeRows and added rows to the control using the Rows.NewRow() method.
IMPROVE. RadGridView - when sorting grouped combo box column the DisplayMemberSort is not taken into consideration
The binding source filtering should be synchronized with the grid one in case other controls are using the same binding source.
To reproduce: - add RadGridView and fill it with data; - use the following code for saving the layout: string layout; using (MemoryStream ms = new MemoryStream()) { radGridView1.SaveLayout(ms); ms.Position = 0; byte[] buffer = new byte[ms.Length - 1]; ms.Read(buffer, 0, buffer.Length); layout = Convert.ToBase64String(buffer); ms.Close(); } When you try to load the saved layout, using the following code, DataException is thrown: using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(layout))) { radGridView1.LoadLayout(stream); } Workaround: save the layout in xml file
ConditionalFormattingObjects should be cleared or they should be applied after rebinding completes. WORKAROUND: save the ConditionalFormattingObjects, reset the data source and then restore them in order to overcome the observed error:
To reproduce: Dim RadGridView1 As New RadGridView Me.Controls.Add(RadGridView1) RadGridView1.Dock = DockStyle.Fill Dim r As New Random() Dim table As New DataTable() table.Columns.Add("ID", GetType(Integer))
To reproduce: 1. Add RadGridView with 3 columns and add summary row 2. When is fired the ViewCellFormatting event, set the Text property of GridSummaryCellElement 3. Run project and text is not visible. void radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e) { GridSummaryCellElement summaryCell = e.CellElement as GridSummaryCellElement; if (summaryCell != null) { if (summaryCell.ColumnInfo.FieldName == "ProductID") { summaryCell.Text = "Total"; } } } Workaround: Set FormatString property instead Text property void radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e) { GridSummaryCellElement summaryCell = e.CellElement as GridSummaryCellElement; if (summaryCell != null) { if (summaryCell.ColumnInfo.FieldName == "ProductID") { summaryCell.FormatString = "Total"; } } }
To reproduce: -add RadGridView and use the following code: public Form1() { InitializeComponent(); radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; radGridView1.AddNewRowPosition = SystemRowPosition.Bottom; radGridView1.Columns.Add("A"); radGridView1.Columns.Add("B"); radGridView1.Columns.Add("C"); radGridView1.CellValidating += radGridView1_CellValidating; } void radGridView1_CellValidating(object sender, CellValidatingEventArgs e) { if ((string)e.Value == "11") { e.Cancel = true; } } Follow the steps: 1. First go to A and enter some value, hit TAB and go to B and enter some value. 2. Hit TAB and move to C. 3. Enter "11". 4. Hit TAB. Validation fails, but the new row is entered (calling radGridView1_RowValidating and ignoring e.Cancel = true; of radGridView1_CellValidating) 5. The erroneous value is copied to Column C in the new "new row". 6. radGridView1_CellValidating is called again. Workaround: BaseGridBehavior gridBehavior = radGridView1.GridBehavior as BaseGridBehavior; gridBehavior.UnregisterBehavior(typeof(GridViewNewRowInfo)); gridBehavior.RegisterBehavior(typeof(GridViewNewRowInfo), new CustomGridNewRowBehavior()); public class CustomGridNewRowBehavior : GridNewRowBehavior { protected override bool ProcessTabKey(KeyEventArgs keys) { GridViewNewRowInfo newRowInfo = (GridViewNewRowInfo)this.GridViewElement.CurrentRow; if (newRowInfo.PinPosition == PinnedRowPosition.Bottom || newRowInfo.RowPosition == SystemRowPosition.Bottom) { FieldInfo fi = this.GridControl.GridBehavior.GetType().GetField("defaultRowBehavior", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); GridRowBehavior rowBehavior = fi.GetValue(this.GridControl.GridBehavior) as GridRowBehavior; MethodInfo mi = rowBehavior.GetType().GetMethod("ProcessTabKey", BindingFlags.NonPublic | BindingFlags.Instance); return (bool)mi.Invoke(rowBehavior, new object[] { keys }); } return base.ProcessTabKey(keys); } }
To reproduce: -add a RadGridView and a RadButton; use the following code: public Form1() { InitializeComponent(); //Create a child template GridViewTemplate childTemplate = new GridViewTemplate(); childTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; this.radGridView1.Templates.Add(childTemplate); GridViewRelation relation = new GridViewRelation(); relation.ChildTemplate = childTemplate; relation.ParentTemplate = this.radGridView1.MasterTemplate; relation.ChildColumnNames.Add("B1"); relation.ParentColumnNames.Add("A1"); this.radGridView1.Relations.Add(relation); } private DataTable dtParent; private DataTable dtChild; private void Form1_Load(object sender, EventArgs e) { //Add data dtParent = new DataTable(); dtParent.Columns.AddRange(new DataColumn[] { new DataColumn("A1") }); dtChild = new DataTable(); dtChild.Columns.AddRange(new DataColumn[] { new DataColumn("B1"), new DataColumn("B2") }); DataRow dr = dtParent.NewRow(); dr["A1"] = "0"; dtParent.Rows.Add(dr); for (int i = 0; i < 40; i++) { DataRow drChild = dtChild.NewRow(); drChild["B1"] = "0"; drChild["B2"] = ""; dtChild.Rows.Add(drChild); } this.radGridView1.MasterTemplate.DataSource = dtParent; this.radGridView1.Templates[0].DataSource = dtChild; } private void radButton1_Click(object sender, EventArgs e) { DataRow drNew = this.dtChild.NewRow(); drNew["B1"] = "0"; drNew["B2"] = "New"; this.dtChild.Rows.Add(drNew); } If you expand the first parent row and scroll down to the last child row, clicking over the button does not refresh the vertical scroll-bar correctly. The new row shows only half. You can not scroll to the end. Workaround: refresh the vertical scroll-bar manually: private void radButton1_Click(object sender, EventArgs e) { DataRow drNew = this.dtChild.NewRow(); drNew["B1"] = "0"; drNew["B2"] = "New"; this.dtChild.Rows.Add(drNew); int val = radGridView1.TableElement.VScrollBar.Value; foreach (GridViewRowInfo row in radGridView1.Rows) { if (row.IsExpanded) { val = radGridView1.TableElement.VScrollBar.Value; row.IsExpanded = false; row.IsExpanded = true; radGridView1.TableElement.VScrollBar.Value = val; } } }
To reproduce: -add RadGridView with 2 columns - ID and Name; -add RadButton and use the following code: public Form1() { InitializeComponent(); AddSelfReferencingColumns(grid, "Id", "Parent.Id"); this.grid.DataSource = TestDataGenerator.GenerateTestData(); } public void AddSelfReferencingColumns(RadGridView grid, string childKey, string parentKey) { GridViewTextBoxColumn col1 = new GridViewTextBoxColumn("hiddenColumnId", childKey); GridViewTextBoxColumn col2 = new GridViewTextBoxColumn("hiddenColumnParentId", parentKey); grid.MasterTemplate.Columns.Add(col1); grid.MasterTemplate.Columns.Add(col2); grid.Columns["hiddenColumnId"].IsVisible = false; grid.Columns["hiddenColumnParentId"].IsVisible = false; grid.Relations.AddSelfReference(grid.MasterTemplate, "hiddenColumnId", "hiddenColumnParentId"); } void refreshButton_Click(object sender, System.EventArgs e) { this.grid.DataSource = TestDataGenerator.GenerateTestData(); } class TestDataGenerator { public static IList<TestObject> GenerateTestData() { IList<TestObject> result = new List<TestObject>(); TestObject top = new TestObject { Id = 1, Name = "Top" }; result.Add(top); for (int i = 1; i < 4; i++) { TestObject firstChild = new TestObject() { Id = 10 * i, Name = string.Format("First level child {0}", i), Parent = top }; result.Add(firstChild); for (int j = 1; j < 10; j++) { TestObject secondChild = new TestObject() { Id = 10 * i + j, Name = string.Format("Second level child {0}", j), Parent = firstChild }; result.Add(secondChild); } } return result; } } class TestObject { public long Id { get; set; } public string Name { get; set; } public TestObject Parent { get; set; } } Steps to reproduce: 1.Type in Name column filter i.e. "F" 2.Press refresh button. The grid is empty, even though the new list contains the same data (different objects). Workaround: void refreshButton_Click(object sender, System.EventArgs e) { FilterDescriptorCollection filters = new FilterDescriptorCollection(); foreach (FilterDescriptor filterItem in this.grid.FilterDescriptors) { filters.Add(filterItem); } this.grid.DataSource = TestDataGenerator.GenerateTestData(); this.grid.FilterDescriptors.Clear(); foreach (FilterDescriptor filter in filters) { this.grid.FilterDescriptors.Add(filter); } }
To reproduce: - add RadGridView and populate manually with hierarchical data; - BestFitColumns method of the child template does not work as expected; #1 scenario: radGridView1.MasterTemplate.ExpandAll(); radGridView1.Templates[0].ExpandAll(); radGridView1.Templates[0].BestFitColumns(BestFitColumnMode.AllCells); You will notice that some of the columns in the child template are not wide enough to show the whole cell content; #2 scenario: Subscribe to the ChildViewExpanded event and call BestFitColumns: private void radGridView1_ChildViewExpanded(object sender, ChildViewExpandedEventArgs e) { e.ChildViewInfo.ViewTemplate.BestFitColumns(BestFitColumnMode.AllCells); } As a result the firstly expanded child view adjusts child template columns width and if you expand another child view which needs greater columns width, it is not displayed correctly. Workaround: determine the column width according to the longest cell content: foreach (GridViewDataColumn col in radGridView1.Templates[0].Columns) { BestFitAllCells(col); } private void BestFitAllCells(GridViewColumn column) { MasterGridViewTemplate masterTemplate = column.OwnerTemplate.Parent as MasterGridViewTemplate; if (masterTemplate == null) { return; } RadGridView grid = masterTemplate.Owner; IVirtualizedElementProvider<GridViewRowInfo> rowProvider = grid.TableElement.RowElementProvider; IVirtualizedElementProvider<GridViewColumn> cellProvider = grid.TableElement.ColumnScroller.ElementProvider; float width = 0; foreach (GridViewRowInfo dataRow in column.OwnerTemplate.Rows) { GridRowElement row = rowProvider.GetElement(dataRow, null) as GridRowElement; row.InitializeRowView(grid.TableElement); row.Initialize(dataRow); row.UpdateInfo(); grid.TableElement.Children.Add(row); row.ResetLayout(true); GridVirtualizedCellElement cell = cellProvider.GetElement(column, row) as GridVirtualizedCellElement; cell.Attach(column, row); cell.SetContent(); cell.UpdateInfo(); row.Children.Add(cell); GridHeaderCellElement headerCell = cell as GridHeaderCellElement; if (headerCell != null) { headerCell.UpdateArrowState(); } cell.ResetLayout(true); width = Math.Max(width, this.GetCellDesiredWidth(cell)); row.Children.Remove(cell); grid.TableElement.Children.Remove(row); this.Detach(cellProvider, cell); this.Detach(rowProvider, row); } width = Math.Max(width, TextRenderer.MeasureText(column.HeaderText, grid.Font).Width); column.Width = (int)width; } private float GetCellDesiredWidth(GridCellElement cell) { cell.Measure(new SizeF(float.PositiveInfinity, float.PositiveInfinity)); return cell.DesiredSize.Width; } private void Detach(IVirtualizedElementProvider<GridViewColumn> elementProvider, GridCellElement cell) { GridVirtualizedCellElement virtualizedCell = cell as GridVirtualizedCellElement; if (virtualizedCell != null) { elementProvider.CacheElement(virtualizedCell); virtualizedCell.Detach(); return; } cell.Dispose(); } private void Detach(IVirtualizedElementProvider<GridViewRowInfo> elementProvider, GridRowElement row) { GridVirtualizedRowElement virtualizedRоw = row as GridVirtualizedRowElement; if (virtualizedRоw != null) { elementProvider.CacheElement(virtualizedRоw); virtualizedRоw.Detach(); return; } row.Dispose(); }
To reproduce: - add RadGridView and populate it manually with hierarchical data; - open one row child rows and select several child rows; - right click to open the context menu and select Copy; - paste in Notepad for example. As a result there is no pasted data. Workaround: radGridView1.ContextMenuOpening += radGridView1_ContextMenuOpening; string clipBoard = string.Empty; RadGridView contextMenuInvoker; void radGridView1_ContextMenuOpening(object sender, Telerik.WinControls.UI.ContextMenuOpeningEventArgs e) { RadGridView grid = sender as RadGridView; if (grid.CurrentCell is GridDataCellElement || grid.CurrentCell is GridTableBodyElement) { if (grid.CurrentRow.ViewTemplate != grid.MasterGridViewTemplate && !(grid.CurrentCell.RowInfo is GridViewNewRowInfo)) { RadMenuItem itemCopy = new RadMenuItem(); itemCopy.Text = "Copy Row(s)"; itemCopy.Click += new EventHandler(itemCopy_Click); e.ContextMenu.Items.RemoveAt(3); e.ContextMenu.Items.Insert(3, itemCopy); e.ContextMenu.Items.RemoveAt(4); } contextMenuInvoker = grid; } } void itemCopy_Click(object sender, EventArgs e) { CopyRows(contextMenuInvoker); } private void CopyRows(RadGridView radGridView) { StringBuilder sb = new StringBuilder(); foreach (GridViewRowInfo row in radGridView.SelectedRows) { int i = 0; while (i < row.Cells.Count) { if (i > 0) { sb.Append(","); } sb.Append(row.Cells[i].Value.ToString()); i++; } sb.AppendLine(";"); } clipBoard = sb.ToString(); Clipboard.SetDataObject(clipBoard); }
To reproduce: 1.Bind RadGridView to hierarchical data - no vertical scroll-bar is visible. 2.Select a certain row and expand the child template (click the expander) - vertical scroll-bar appears. 3.Scroll several rows downwards. 4.Click the expander to close the child template (the vertical scroll-bar should hide). As a result the selected row is changed. Workaround: follow the approach below: GridViewHierarchyRowInfo row = null; bool keepParentRow = false; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.productsTableAdapter.Fill(this.nwindDataSet.Products); this.categoriesTableAdapter.Fill(this.nwindDataSet.Categories); radGridView1.AutoGenerateHierarchy = true; radGridView1.DataSource = this.nwindDataSet; radGridView1.DataMember = "Categories"; radGridView1.CurrentRowChanging += radGridView1_CurrentRowChanging; radGridView1.ChildViewExpanded += radGridView1_ChildViewExpanded; radGridView1.MouseDown += radGridView1_MouseDown; } private void radGridView1_CurrentRowChanging(object sender, CurrentRowChangingEventArgs e) { RadGridView grid = sender as RadGridView; if (grid != null && row != null && keepParentRow) { e.Cancel = true; } } private void radGridView1_MouseDown(object sender, MouseEventArgs e) { RadGridView grid = sender as RadGridView; if (grid != null) { GridExpanderItem expander = grid.ElementTree.GetElementAtPoint(e.Location) as GridExpanderItem; if (expander != null && row != null) { keepParentRow = true; } else { keepParentRow = false; } } } private void radGridView1_ChildViewExpanded(object sender, Telerik.WinControls.UI.ChildViewExpandedEventArgs e) { RadGridView grid = sender as RadGridView; if (grid != null && e.IsExpanded == false) { row = e.ParentRow as GridViewHierarchyRowInfo; } }
To reproduce: -add RadDock with ToolWindow; -add RadGridView inside the ToolWindow; -apply Office2010Blue theme to the entire application; By default the GridDataCellElement has Font Segoe UI, 8.25pt with blue fore color. When the ToolWindow is floating, GridDataCellElement's font is changed to Microsoft Sans Serif, 8.25pt with black fore color. Workaround: customize the theme by setting the appropriate font and fore color to the GridDataCellElement for the necessary element states.
Description: hover the last row bottom border in such a way to display re-sizing cursor. Then move the cursor downwards. The problem occurs only when you have a few rows and move the cursor to the blank side of the grid view. To reproduce: -add RadGridView and use the following code: private void Form1_Load(object sender, EventArgs e) { this.customersTableAdapter.Fill(this.nwindDataSet.Customers); foreach (DataColumn column in this.nwindDataSet.Customers.Columns) { this.radGridView1.Columns.Add(column.ColumnName); } object[] row = this.nwindDataSet.Customers.Rows[0].ItemArray; this.radGridView1.Rows.Add(row); this.radGridView1.SelectedRows[0].IsSelected = false; this.radGridView1.CurrentCell.IsCurrent = false; this.radGridView1.CurrentRow.IsCurrent = false; } Workaround: public Form1() { InitializeComponent(); this.radGridView1.GridBehavior = new MyBaseBehavior(); } public class MyBaseBehavior : BaseGridBehavior { public override bool OnMouseMove(MouseEventArgs e) { GridRowElement currentRow = this.RowAtPoint; if (currentRow == null && e.Button == MouseButtons.None && Cursor.Current != Cursors.Default) { Cursor.Current = Cursors.Default; } return base.OnMouseMove(e); } }
To reproduce: 1.Use the Self-Referencing Hierarchy help article to fill the grid with data. 2.Subscribe to the ChildViewExpanding event and use the following code snippet: private void radGridView1_ChildViewExpanding(object sender, ChildViewExpandingEventArgs e) { if (e.ParentRow.ChildRows != null && e.ParentRow.ChildRows.Count > 0) { e.ParentRow.ChildRows[0].Delete(); } }
To reproduce: void grid_RowValidating(object sender, RowValidatingEventArgs e) { e.Cancel = true; } Pressing the escape key should cancel the edit mode and revert the value