To reproduce: - Add a grid to a form and set the EnableHotTracking property to false in the properties window. - When the application is started the property is reset. Workaround: Set the property at runtime.
To reproduce: add a RadGridView and a RadButton on the form. Use the following code snippet: public RadForm1() { InitializeComponent(); this.radGridView1.Columns.Add("Col1"); this.radGridView1.Columns.Add("Col2"); for (int i = 0; i < 5; i++) { this.radGridView1.Rows.Add(i, "Item" + i); } this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.RowValidating += radGridView1_RowValidating; this.radGridView1.UserAddingRow += radGridView1_UserAddingRow; } private void radGridView1_UserAddingRow(object sender, Telerik.WinControls.UI.GridViewRowCancelEventArgs e) { e.Cancel = true; } private void radGridView1_RowValidating(object sender, Telerik.WinControls.UI.RowValidatingEventArgs e) { if (e.Row.IsModified && e.Row is GridViewDataRowInfo) { e.Cancel = true; } } private void radButton1_Click(object sender, EventArgs e) { RadMessageBox.Show("Clicked"); } 1. Select a data cell and activate the editor. Enter some new value and click the button. The Click event is fired. 2. Select the new row and activate the editor. Enter some value and click the button. The Click event is NOT fired. Workaround: use the CellValidating event instead.
All event handlers should be made virtual. All controls should be public or have properties.
A developer should be able to remove certain fields from there, so his end-users cannot use them to build their expressions.
To reproduce: - Add several columns including combo-box columns to a grid. - Add one row and upon a button click, change the data source of the combo column. Workaround: Seth the following field to null prior changing the data source: GetType(GridViewComboBoxColumn).GetField("nullBoundItem", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic).SetValue(combo, Nothing) combo.DataSource = dt
Implement the 'substring' function for calculated columns.
The AllowNaturalSort property should indicate whether the no-sort state when changing sort order will be allowed. Workaround: Private Sub SortChanging(sender As Object, e As Telerik.WinControls.UI.GridViewCollectionChangingEventArgs) If e.Action = NotifyCollectionChangedAction.Remove AndAlso e.OldValue = ListSortDirection.Descending Then e.Cancel = True For Each sd As SortDescriptor In Me.RadGridView1.SortDescriptors If sd.PropertyName = e.PropertyName Then sd.Direction = ListSortDirection.Ascending End If Next End If End Sub
To reproduce: private void Form1_Load(object sender, EventArgs e) { this.suppliersTableAdapter.Fill(this.nwindDataSet.Suppliers); this.productsTableAdapter.Fill(this.nwindDataSet.Products); radGridView1.DataSource = nwindDataSet.Suppliers; radGridView1.BestFitColumns(BestFitColumnMode.AllCells); GridViewTemplate template = CreateTemplate(this.productsBindingSource); template.DataSource = nwindDataSet.Products; radGridView1.MasterTemplate.Templates.Add(template); GridViewRelation relation = new GridViewRelation(radGridView1.MasterTemplate); relation.ChildTemplate = template; relation.RelationName = "SuppliersProducts"; relation.ParentColumnNames.Add("SupplierID"); relation.ChildColumnNames.Add("SupplierID"); radGridView1.Relations.Add(relation); } private GridViewTemplate CreateTemplate(BindingSource source) { GridViewTemplate template = new GridViewTemplate(); template.Caption = "TaskTemplate"; template.AllowAddNewRow = false; template.EnableFiltering = true; FilterDescriptor filter = new FilterDescriptor(); filter.PropertyName = "ReorderLevel"; filter.Operator = FilterOperator.IsNotEqualTo; filter.Value = 25; template.FilterDescriptors.Add(filter); template.ShowFilteringRow = false; template.SortDescriptors.Expression = "ProductName ASC, UnitPrice ASC"; template.DataSource = source; template.BestFitColumns(BestFitColumnMode.AllCells); return template; } Workaround: set the filter after the hierarchy setup: private void Form1_Load(object sender, EventArgs e) { this.suppliersTableAdapter.Fill(this.nwindDataSet.Suppliers); this.productsTableAdapter.Fill(this.nwindDataSet.Products); radGridView1.DataSource = nwindDataSet.Suppliers; radGridView1.BestFitColumns(BestFitColumnMode.AllCells); GridViewTemplate template = CreateTemplate(this.productsBindingSource); template.DataSource = nwindDataSet.Products; radGridView1.MasterTemplate.Templates.Add(template); GridViewRelation relation = new GridViewRelation(radGridView1.MasterTemplate); relation.ChildTemplate = template; relation.RelationName = "SuppliersProducts"; relation.ParentColumnNames.Add("SupplierID"); relation.ChildColumnNames.Add("SupplierID"); radGridView1.Relations.Add(relation); FilterDescriptor filter = new FilterDescriptor(); filter.PropertyName = "ReorderLevel"; filter.Operator = FilterOperator.IsNotEqualTo; filter.Value = 25; template.FilterDescriptors.Add(filter); } private GridViewTemplate CreateTemplate(BindingSource source) { GridViewTemplate template = new GridViewTemplate(); template.Caption = "TaskTemplate"; template.AllowAddNewRow = false; template.EnableFiltering = true; template.ShowFilteringRow = false; template.SortDescriptors.Expression = "ProductName ASC, UnitPrice ASC"; template.DataSource = source; template.BestFitColumns(BestFitColumnMode.AllCells); return template; }
To reproduce: DataTable dt = new DataTable(); public Form1() { InitializeComponent(); for (int i = 0; i < 5; i++) { dt.Columns.Add("Col" + i); } for (int i = 0; i < 5; i++) { DataRow row = dt.NewRow(); dt.Rows.Add(row); foreach (DataColumn col in dt.Columns) { row[col.ColumnName] = randomWord(2, 14); } } } static Random r = new Random(); static string chars = "AEIOUBCDFGHJKLMNPQRSTVWXYZ"; static string randomWord(int minlen, int maxlen) { double d1 = minlen + r.NextDouble() * (maxlen - minlen); int len = (int)d1; char[] word = new char[len]; for (int i = 0; i < len; ++i) { int index = ((int)Math.Round(25 * r.NextDouble() + 0.4999999999)); word[i] = chars[index]; } return new string(word); } public class Item { public int Id { get; set; } public string Name { get; set; } public Item(int id, string name) { this.Id = id; this.Name = name; } } private void radButton1_Click(object sender, EventArgs e) { this.radGridView1.Columns.Clear(); foreach (DataColumn col in dt.Columns) { this.radGridView1.Columns.Add(col.ColumnName); this.radGridView1.Columns.Last().FieldName = col.ColumnName; } this.radGridView1.BestFitColumns(BestFitColumnMode.AllCells); } private void Form1_Load(object sender, EventArgs e) { this.radGridView1.AutoGenerateColumns = false; this.radGridView1.DataSource = dt; foreach (DataColumn col in dt.Columns) { this.radGridView1.Columns.Add(col.ColumnName); this.radGridView1.Columns.Last().FieldName = col.ColumnName; } this.radGridView1.BestFitColumns(BestFitColumnMode.AllCells); } Workaround: clear the GroupDescriptors collection as well and add the GroupDescriptor programmatically: http://docs.telerik.com/devtools/winforms/gridview/grouping/setting-groups-programmatically
To reproduce: - Select several rows and cells in excel and copy them. - Paste in the self-reference grid. - Only the first row is copied. Workaround: private void RadGridView1_Pasting(object sender, GridViewClipboardEventArgs e) { e.Cancel = true; List<List<string>> rows = this.GetTextData(); PrintGridTraverser traverser = new PrintGridTraverser(this.radGridView1.MasterView); while (traverser.Current != this.radGridView1.CurrentRow) { traverser.MoveNext(); } traverser.MovePrevious(); int rowIndex = 0; int colIndex = this.radGridView1.CurrentColumn.Index; while (traverser.MoveNext() && rowIndex < rows.Count) { for (int i = colIndex; i < this.radGridView1.Columns.Count && i - colIndex < rows[rowIndex].Count; i++) { traverser.Current.Cells[i].Value = rows[rowIndex][i - colIndex]; } rowIndex++; } }
To reproduce: - Add GridViewTextBoxColumn and set the MaxLength property. - Paste in data row while the is not in edit mode. Workaround: private void RadGridView1_Pasting(object sender, Telerik.WinControls.UI.GridViewClipboardEventArgs e) { if (radGridView1.CurrentColumn.Name == "column1") { GridViewTextBoxColumn col = new GridViewTextBoxColumn(); var lenght = col.MaxLength; if (Clipboard.ContainsData(DataFormats.Text)) { e.Cancel = true; string data = Clipboard.GetData(DataFormats.Text).ToString(); radGridView1.CurrentCell.Value = data.Substring(0, lenght); } } }
Please refer to the attached sample project and gif files. The user is not allowed to drop in the first half of the row element. However, the drop operation is allowed in the second half. Once the RadDragOverEventArgs.CanDrop property is set to false, the before/after row hint is disposed and it is not shown for this row anymore. Workaround: public class CustomRadGridViewDragDropService : RadGridViewDragDropService { public CustomRadGridViewDragDropService(RadGridViewElement gridViewElement) : base(gridViewElement) { } public override string Name { get { return typeof(RadGridViewDragDropService).Name; } } protected override void OnPreviewDragOver(RadDragOverEventArgs e) { base.OnPreviewDragOver(e); SetDragDropBehavior(); Point p = this.GridViewElement.ElementTree.Control.PointToClient(Cursor.Position); UpdateDragHintLocation(p); } } this.radGridView1.GridViewElement.RegisterService(new CustomRadGridViewDragDropService(this.radGridView1.GridViewElement));
To reproduce: populate the grid with data and use the code snippet below: public Form1() { InitializeComponent(); this.radGridView1.EnablePaging = true; this.radGridView1.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Bottom; } Select the third page and click the new row at the bottom. The editor is activated as expected but the first page is made current. Workaround: use the CellEditorInitialized event and move to the desired page private void radGridView1_CellEditorInitialized(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e) { if (e.Row is GridViewNewRowInfo) { this.radGridView1.MasterTemplate.MoveToPage(2); } }
Note: if you change the image in Windows8 theme for example, the image is successfully applied. Workaround: set the CurrentRowHeaderImage property at run time.
Workaround: create a custom RadListFilterPopup private void radGridView1_FilterPopupRequired(object sender, FilterPopupRequiredEventArgs e) { e.FilterPopup = new MyRadListFilterPopup(e.Column); } public class MyRadListFilterPopup : RadListFilterPopup { public MyRadListFilterPopup(GridViewDataColumn dataColumn) : base(dataColumn, false) { } protected override RadListFilterDistinctValuesTable GetDistinctValuesTable() { if (this.DataColumn.OwnerTemplate.HierarchyLevel == 0) { return base.GetDistinctValuesTable(); } GridViewColumnValuesCollection distinctValues = this.GetDistinctValuesWithFilter(this.DataColumn); RadListFilterDistinctValuesTable valuesTable = new RadListFilterDistinctValuesTable(); valuesTable.FormatString = this.DataColumn.FormatString; valuesTable.DataConversionInfoProvider = this.DataColumn; GridViewComboBoxColumn comboBoxColumn = this.DataColumn as GridViewComboBoxColumn; if (comboBoxColumn != null && !String.IsNullOrEmpty(comboBoxColumn.ValueMember)) { foreach (object value in distinctValues) { if (value != null && value != System.DBNull.Value) { object rowValue = value; object lookupValue = ((GridViewComboBoxColumn)this.DataColumn).GetLookupValue(value); if (comboBoxColumn.FilteringMode == GridViewFilteringMode.DisplayMember) { rowValue = lookupValue; } if (lookupValue != null) { valuesTable.Add(lookupValue.ToString(), rowValue); } } } } else { foreach (object value in distinctValues) { valuesTable.Add(value); } } return valuesTable; } private GridViewColumnValuesCollection GetDistinctValuesWithFilter(GridViewDataColumn column) { GridViewColumnValuesCollection distinctValues = new GridViewColumnValuesCollection(); int count = column.OwnerTemplate.ExcelFilteredColumns.Count; if ((count > 0 && column == column.OwnerTemplate.ExcelFilteredColumns[count - 1]) || column.OwnerTemplate.HierarchyLevel > 0) { if (count == 1 || column.OwnerTemplate.HierarchyLevel > 0) { int index = column.Index; if (index >= 0) { IList<GridViewRowInfo> templateRows = column.OwnerTemplate.Rows; if (templateRows.Count == 0 && column.OwnerTemplate.Parent != null && column.OwnerTemplate.HierarchyLevel > 0) { templateRows = new List<GridViewRowInfo>(); GridViewInfo templateViewInfo = column.OwnerTemplate.MasterViewInfo; for (int i = 0; i < column.OwnerTemplate.Parent.Rows.Count; i++) { GridViewRowInfo parentRow = column.OwnerTemplate.Parent.Rows[i]; ((List<GridViewRowInfo>)templateRows).AddRange(column.OwnerTemplate.HierarchyDataProvider.GetChildRows(parentRow, templateViewInfo)); } } foreach (GridViewRowInfo row in templateRows) { object cellValue = row.Cells[index].Value; if (!distinctValues.Contains(cellValue)) { distinctValues.Add(cellValue); } } if (distinctValues.Count > 0) { return distinctValues; } } } } return distinctValues; } }
Workaround: create a custom GridDetailViewCellElement Public Class Form1 Sub New() InitializeComponent() AddHandler dgvPatients.CreateCell, AddressOf dgvPatients_CreateCell End Sub Private Sub dgvPatients_CreateCell(sender As Object, e As GridViewCreateCellEventArgs) If e.CellType = GetType(GridDetailViewCellElement) Then e.CellElement = New MyGridDetailViewCellElement(e.Column, e.Row) End If End Sub End Class Public Class MyGridDetailViewCellElement Inherits GridDetailViewCellElement Sub New(column As GridViewColumn, rowElement As GridRowElement) MyBase.New(column, rowElement) End Sub Public Overrides Sub UpdateTabItemsVisibility() If Me.DetailsRow Is Nothing Then Return End If MyBase.UpdateTabItemsVisibility() End Sub End Class
To reproduce: populate a grid and enable multiple selection. Use cell selection. When you click the row header, the entire row (all cells from the row) is selected no matter the SelectionMode. However, if you start a selection from the row header and move the cursor, only the cells from the first column get selected. The attached gif file illustrates the behavior. The expected behavior is that all cells from the affected columns should be selected when starting the selection from the row header. Workaround: Sub New() InitializeComponent() Me.RadGridView1.MultiSelect = True Me.RadGridView1.SelectionMode = Telerik.WinControls.UI.GridViewSelectionMode.CellSelect AddHandler Me.RadGridView1.MouseDown, AddressOf GridMouseDown AddHandler Me.RadGridView1.MouseUp, AddressOf GridMouseUp AddHandler Me.RadGridView1.MouseMove, AddressOf GridMouseMove End Sub Dim isMouseDown = False Dim startRow As GridViewRowInfo Dim lastHoveredCell As GridCellElement Private Sub GridMouseDown(sender As Object, e As MouseEventArgs) Dim cell As GridRowHeaderCellElement = TryCast(Me.RadGridView1.ElementTree.GetElementAtPoint(e.Location), GridRowHeaderCellElement) If cell IsNot Nothing Then isMouseDown = True startRow = cell.RowInfo End If End Sub Private Sub GridMouseUp(sender As Object, e As MouseEventArgs) isMouseDown = False startRow = Nothing End Sub Private Sub GridMouseMove(sender As Object, e As MouseEventArgs) If isMouseDown Then Dim cellUnderMouse As GridCellElement = TryCast(Me.RadGridView1.ElementTree.GetElementAtPoint(e.Location), GridCellElement) If cellUnderMouse IsNot Nothing AndAlso Not cellUnderMouse.Equals(lastHoveredCell) Then lastHoveredCell = cellUnderMouse Me.RadGridView1.ClearSelection() Me.RadGridView1.SelectedCells.BeginUpdate() If startRow.Index > cellUnderMouse.RowInfo.Index Then For index = cellUnderMouse.RowInfo.Index To startRow.Index Me.RadGridView1.Rows(index).IsSelected = True Next Else For index = startRow.Index To cellUnderMouse.RowInfo.Index For Each cell As GridViewCellInfo In Me.RadGridView1.Rows(index).Cells cell.IsSelected = True Next Next End If Me.RadGridView1.SelectedCells.EndUpdate(True) End If End If End Sub
The behavior should be consistent no matter if you change the current column or the current row.