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
Steps to reproduce: 1. expand a parent row 2. remove the first child row (e.g. 'Jon Smith') by selecting the child row and press the button at the top 3. remove the second (last) child row (in this case 'Pete van Dijk') the same way Here is the code snippet: public partial class Form1 : Form { private List<Department> _departments; public Form1() { InitializeComponent(); SetGridParentColumns(); SetGridChildTemplate(); InitData(); grid.RowSourceNeeded += grid_RowSourceNeeded; } private void InitData() { _departments = new List<Department>(2); Department dep1 = new Department() { DepartmentId = 1, Name = "Accounting" }; Department dep2 = new Department() { DepartmentId = 2, Name = "Finance" }; Employee emp1 = new Employee() { DepartmentId = 1, EmployeeId = 1, FirsName = "John", LastName = "Smith" }; Employee emp2 = new Employee() { DepartmentId = 1, EmployeeId = 2, FirsName = "Pete", LastName = "van Dijk" }; Employee emp3 = new Employee() { DepartmentId = 2, EmployeeId = 3, FirsName = "Mark", LastName = "Smith" }; Employee emp4 = new Employee() { DepartmentId = 2, EmployeeId = 4, FirsName = "Jan", LastName = "Janssen" }; dep1.Employees = new List<Employee>() { emp1, emp2 }; dep2.Employees = new List<Employee>() { emp3, emp4 }; _departments.Add(dep1); _departments.Add(dep2); grid.DataSource = _departments; grid.AllowAddNewRow = false; grid.BestFitColumns(); } private void SetGridParentColumns() { grid.AutoGenerateColumns = false; grid.Columns.Add("DepartmentId", "DepartmentId", "DepartmentId"); grid.Columns.Add("Name", "Name", "Name"); } private void SetGridChildTemplate() { grid.Templates.Clear(); GridViewTemplate childTemplate = new GridViewTemplate(); childTemplate.Columns.Add("EmployeeId"); childTemplate.Columns.Add("DepartmentId"); childTemplate.Columns.Add("FirstName"); childTemplate.Columns.Add("LastName"); grid.Templates.Add(childTemplate); childTemplate.HierarchyDataProvider = new GridViewEventDataProvider(childTemplate); } private void grid_RowSourceNeeded(object sender, GridViewRowSourceNeededEventArgs e) { Department dep = e.ParentRow.DataBoundItem as Department; foreach (Employee employee in dep.Employees) { GridViewRowInfo gridRow = e.Template.Rows.NewRow(); gridRow.Cells["EmployeeId"].Value = employee.EmployeeId; gridRow.Cells["DepartmentId"].Value = employee.DepartmentId; gridRow.Cells["FirstName"].Value = employee.FirsName; gridRow.Cells["LastName"].Value = employee.LastName; e.SourceCollection.Add(gridRow); } e.Template.AllowAddNewRow = false; e.Template.BestFitColumns(); } private void btnRemoveChildRow_Click(object sender, EventArgs e) { GridViewRowInfo row = grid.SelectedRows[0]; if (row.ViewTemplate.Parent == null) return; //department (parent) row, so don't remove it int employeeId = Convert.ToInt32(row.Cells["EmployeeId"].Value); int departmentId = Convert.ToInt32(row.Cells["DepartmentId"].Value); Department dep = GetDepartment(departmentId); dep.RemoveEmployee(employeeId); row.ViewTemplate.Refresh(); } private Department GetDepartment(int departmentId) { foreach (Department dep in _departments) if (dep.DepartmentId == departmentId) return dep; return null; } } public class Department { public int DepartmentId { get; set; } public string Name { get; set; } public List<Employee> Employees { get; set; } public void RemoveEmployee(int employeeId) { Employee empToRemove = null; foreach (Employee emp in Employees) { if (emp.EmployeeId == employeeId) { empToRemove = emp; break; } } if (empToRemove != null) Employees.Remove(empToRemove); } } public class Employee { public int DepartmentId { get; set; } public int EmployeeId { get; set; } public string FirsName { get; set; } public string LastName { get; set; } } Workaround: use the ViewInfo.Refresh method instead of the ViewTemplate.Refresh method
To reproduce: - Add MultiColumnComboBoxColumn to a blank grid. - Subscribe to the SelectedIndexChanged event of the corresponding ActiveEditor (RadMultiColumnComboBoxElement). - You will notice that when you select different cells the event is fired several times.
To reproduce: Add a RadGridView and bind it to a DataTable. Subscribe to the TableElement's vertical scroll's ValueChanged event and add new data when the value reaches the maximum: private void RequestData(int startFrom, int count) { for (int i = 0; i < count; i++) { DataRow row = dt.NewRow(); row["ID"] = startFrom + i; dt.Rows.Add(row); } } private void VScrollBar_ValueChanged(object sender, EventArgs e) { if (dgwData.TableElement.VScrollBar.Value + dgwData.TableElement.VScrollBar.LargeChange >= dgwData.TableElement.VScrollBar.Maximum) { int maxVScrollBarBefore = dgwData.TableElement.VScrollBar.Maximum; dgwData.SelectionChanged -= dgwData_SelectionChanged; dgwData.TableElement.VScrollBar.ValueChanged -= VScrollBar_ValueChanged; RequestData(dt.Rows.Count, rowsToCharge); dgwData.SelectionChanged += dgwData_SelectionChanged; dgwData.TableElement.VScrollBar.ValueChanged += VScrollBar_ValueChanged; } } You will notice that when you use the mousewheel the scrollbar is being updated, but when you use the arrows it is not. Workaround: Invoke the UpdateScrollRange method of the TableElement's RowScroller after adding the new data: dgwData.TableElement.RowScroller.UpdateScrollRange();
To reproduce: - Set the AutoSizeRows and PrintGrouping properties to true. - Add a group descriptor and then call the PrintPreview method of the grid. Workaround: - Use the following classes to create custom print style: public class MyGridPrintRenderer : TableViewDefinitionPrintRenderer { private RadGridView gridView; public MyGridPrintRenderer(RadGridView grid) : base(grid) { gridView = grid; } protected override int GetDataRowHeight(GridViewRowInfo row, TableViewRowLayoutBase rowLayout) { IVirtualizedElementProvider<GridViewRowInfo> rowElementProvider = this.gridView.TableElement.RowScroller.ElementProvider; GridRowElement visualRow = rowElementProvider.GetElement(row, null) as GridRowElement; if (visualRow is GridGroupHeaderRowElement) { return rowLayout.GetRowHeight(row); } return base.GetDataRowHeight(row, rowLayout); } } public class MyGridPrintSyle : GridPrintStyle { protected override BaseGridPrintRenderer InitializePrintRenderer(RadGridView grid) { if (this.PrintRenderer != null) { this.PrintRenderer.PrintCellPaint -= renderer_PrintCellPaint; this.PrintRenderer.PrintCellFormatting -= renderer_PrintCellFormatting; } MyGridPrintRenderer renderer = new MyGridPrintRenderer(grid); renderer.PrintCellFormatting += renderer_PrintCellFormatting; renderer.PrintCellPaint += renderer_PrintCellPaint; return renderer; } private void renderer_PrintCellPaint(object sender, PrintCellPaintEventArgs e) { this.OnPrintCellPaint(sender, e); } private void renderer_PrintCellFormatting(object sender, PrintCellFormattingEventArgs e) { this.OnPrintCellFormatting(sender, e); } }
To reproduce: Add a RadGridView with a ComboBoxColumn, add a datasource, use the following code on CellEditorInitializedEvent: void GridView_CellEditorInitialized(object sender, GridViewCellEventArgs e) { GridViewComboBoxColumn column = e.Column as GridViewComboBoxColumn; if (column != null) { RadDropDownListEditor editor = e.ActiveEditor as RadDropDownListEditor; if (editor != null) { RadDropDownListEditorElement editorElement = editor.EditorElement as RadDropDownListEditorElement; if (editorElement != null) { editorElement.AutoCompleteMode = AutoCompleteMode.SuggestAppend; } } } } Run the project, select a value from one of the dropdowns, start editing, press backspace, press the key which corresponds to the deleted character, for example if the last character was '2', press the key '2'. You will notice that the key will be ignored. Workaround: void GridView_CellEditorInitialized(object sender, GridViewCellEventArgs e) { GridViewComboBoxColumn column = e.Column as GridViewComboBoxColumn; if (column != null) { RadDropDownListEditor editor = e.ActiveEditor as RadDropDownListEditor; if (editor != null) { RadDropDownListEditorElement editorElement = editor.EditorElement as RadDropDownListEditorElement; editorElement.TextBox.KeyPress -= TextBox_KeyPress; editorElement.TextBox.KeyPress += TextBox_KeyPress; if (editorElement != null) { editorElement.AutoCompleteMode = AutoCompleteMode.SuggestAppend; } } } } private MethodInfo baseMethod = null; void TextBox_KeyPress(object sender, KeyPressEventArgs e) { if (char.IsLetterOrDigit(e.KeyChar)) { RadDropDownListEditorElement editorElement = ((this.GridView.ActiveEditor as RadDropDownListEditor).EditorElement as RadDropDownListEditorElement); MethodInfo method = baseMethod == null ? baseMethod = typeof(AutoCompleteAppendHelper).GetMethod("SetEditableElementText", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) : baseMethod; InvokeNotOverride(method, editorElement.AutoCompleteAppend, editorElement.AutoCompleteAppend.FindShortestString(editorElement.Text + e.KeyChar)); editorElement.TextBox.TextBoxItem.TextBoxControl.SelectionStart = editorElement.Text.Length; } } public object InvokeNotOverride(MethodInfo methodInfo, object targetObject, params object[] arguments) { var parameters = methodInfo.GetParameters(); if (parameters.Length == 0) { if (arguments != null && arguments.Length != 0) throw new Exception("Arguments cont doesn't match"); } else if (parameters.Length != arguments.Length) { throw new Exception("Arguments cont doesn't match"); } Type returnType = null; if (methodInfo.ReturnType != typeof(void)) { returnType = methodInfo.ReturnType; } var type = targetObject.GetType(); var dynamicMethod = new DynamicMethod("", returnType, new Type[] { type, typeof(Object) }, type); var iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4_S, i); iLGenerator.Emit(OpCodes.Ldelem_Ref); var parameterType = parameter.ParameterType; if (parameterType.IsPrimitive) { iLGenerator.Emit(OpCodes.Unbox_Any, parameterType); } else { iLGenerator.Emit(OpCodes.Castclass, parameterType); } } iLGenerator.Emit(OpCodes.Call, methodInfo); iLGenerator.Emit(OpCodes.Ret); return dynamicMethod.Invoke(null, new object[] { targetObject, arguments }); }