Please refer to the attached screenshot and sample video. Workaround: public class CustomGrid : RadGridView { public override string ThemeClassName { get { return typeof(RadGridView).FullName; } } protected override void OnKeyPress(KeyPressEventArgs e) { this.BeginEdit(); if (this.GridViewElement.ActiveEditor is RadDropDownListEditor) { string symbol = e.KeyChar.ToString(); RadDropDownListEditor editor = this.GridViewElement.ActiveEditor as RadDropDownListEditor; RadDropDownListEditorElement element = editor.EditorElement as RadDropDownListEditorElement; if ((element.AutoCompleteMode & AutoCompleteMode.Suggest) == AutoCompleteMode.Suggest) { element.EditableElementText += symbol; element.EditableElement.SelectionStart = 1; element.EditableElement.SelectionLength = 0; } } base.OnKeyPress(e); } }
To reproduce: private void Form1_Load(object sender, EventArgs e) { this.productsTableAdapter.Fill(this.nwindDataSet.Products); this.categoriesTableAdapter.Fill(this.nwindDataSet.Categories); radGridView1.AllowSearchRow = true; radGridView1.DataSource = nwindDataSet.Categories; radGridView1.MasterTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; radGridView1.UseScrollbarsInHierarchy = true; GridViewTemplate template = new GridViewTemplate(); template.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; template.DataSource = nwindDataSet.Products; radGridView1.MasterTemplate.Templates.Add(template); GridViewRelation relation = new GridViewRelation(radGridView1.MasterTemplate); relation.ChildTemplate = template; relation.RelationName = "CategoriesProducts"; relation.ParentColumnNames.Add("CategoryID"); relation.ChildColumnNames.Add("CategoryID"); radGridView1.Relations.Add(relation); } Workaround: private void radGridView1_CurrentRowChanged(object sender, CurrentRowChangedEventArgs e) { if (this.radGridView1.CurrentRow != null) { if (this.radGridView1.CurrentRow.HierarchyLevel > 0) { tableElement.ScrollToRow((GridViewHierarchyRowInfo)(this.radGridView1.CurrentRow).Parent); this.radGridView1.TableElement.EnsureRowVisible((GridViewHierarchyRowInfo)(this.radGridView1.CurrentRow).Parent); tableElement.ScrollToRow(this.radGridView1.CurrentRow); tableElement.EnsureRowVisible(this.radGridView1.CurrentRow); } } }
To reproduce: use the following code snippet. From the filtering box, when you select "Null" and then select "All", the following error occurs: Item has already been added. Key in dictionary: '(Blanks)' Key being added: '(Blanks)' DataTable dt = new DataTable(); dt.Columns.Add("Id", typeof(int)); dt.Columns.Add("Name", typeof(string)); dt.Rows.Add(1,"A"); dt.Rows.Add(2, ""); dt.Rows.Add(3, null); dt.Rows.Add(4, "B"); dt.Rows.Add(5, "C"); dt.Rows.Add(6, ""); this.radGridView1.DataSource = dt; this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.EnableFiltering = true; this.radGridView1.ShowFilteringRow = false; this.radGridView1.ShowHeaderCellButtons = true; Workaround: this.radGridView1.FilterPopupInitialized += radGridView1_FilterPopupInitialized; RadListFilterDistinctValuesTable selectedValues; private void radGridView1_FilterPopupInitialized(object sender, Telerik.WinControls.UI.FilterPopupInitializedEventArgs e) { RadListFilterPopup popup = e.FilterPopup as RadListFilterPopup; selectedValues = popup.MenuTreeElement.SelectedValues; popup.MenuTreeElement.TreeView.NodeCheckedChanged += TreeView_NodeCheckedChanged; } private void TreeView_NodeCheckedChanged(object sender, TreeNodeCheckedEventArgs e) { if (e.Node.CheckState == Telerik.WinControls.Enumerations.ToggleState.Off) { if (selectedValues.Contains(e.Node.Text)) { selectedValues.Remove(e.Node.Text); } } }
Workaround: use a custom BaseGridBehavior public Form1() { InitializeComponent(); this.radGridView1.GridBehavior = new MyBaseGridBehavior(); } public class MyBaseGridBehavior : BaseGridBehavior { public override bool ProcessKey(KeyEventArgs keys) { if (keys.Control && this.GridControl.CurrentColumn == null) { return false; } return base.ProcessKey(keys); } }
Add a Card view layout.
To reproduce: radGridView1.GridNavigator.SelectFirstRow(); for (int i = 0; i < radGridView1.RowCount; i++) { var result = radGridView1.GridNavigator.SelectNextRow(1); } Workaround: - Move to the last row first: radGridView1.GridNavigator.SelectLastRow();
Workaround: suspend columns notifications when preview dropping and resume the notification after the drag drop service has stopped: Dim svc As RadDragDropService = Me.RadGridView1.GridViewElement.GetService(Of RadDragDropService)() AddHandler svc.Stopped, svc_Stopped AddHandler svc.PreviewDragDrop, AddressOf svc_PreviewDragDrop Private Sub svc_PreviewDragDrop(sender As Object, e As RadDropEventArgs) For Each col As GridViewColumn In Me.RadGridView1.Columns col.SuspendPropertyNotifications() Next End Sub Private Function svc_Stopped() As Object For Each col As GridViewColumn In Me.RadGridView1.Columns col.ResumePropertyNotifications() Next End Function
To reproduce: public Form1() { InitializeComponent(); BindingList<Item> items = new BindingList<Item>(); for (int i = 0; i < 30; i++) { if (i % 3 == 0) { items.Add(new Item(i,"Item" + i, IndeterminateBoolean.YesAndNo)); } else if (i % 3 == 1) { items.Add(new Item(i, "Item" + i, IndeterminateBoolean.Yes)); } else { items.Add(new Item(i, "Item" + i, IndeterminateBoolean.No)); } } this.radGridView1.DataSource = items; GridViewCheckBoxColumn checkBox = new GridViewCheckBoxColumn("CheckBoxCol"); checkBox.DataTypeConverter = new IndeterminateBooleanToggleStateConverter(); checkBox.FieldName = "IsActive"; checkBox.ThreeState = true; this.radGridView1.Columns.Add(checkBox); this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; this.radGridView1.EnableFiltering = true; this.radGridView1.ShowHeaderCellButtons = true; this.radGridView1.ShowFilteringRow = false; } public class Item { public int Id { get; set; } public string Name { get; set; } public IndeterminateBoolean IsActive { get; set; } public Item(int id, string name, IndeterminateBoolean isActive) { this.Id = id; this.Name = name; this.IsActive = isActive; } } public enum IndeterminateBoolean { No, Yes, YesAndNo } public class IndeterminateBooleanToggleStateConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(ToggleState); } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return destinationType == typeof(ToggleState); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is ToggleState) { switch ((ToggleState)value) { case ToggleState.On: return IndeterminateBoolean.Yes; case ToggleState.Off: return IndeterminateBoolean.No; case ToggleState.Indeterminate: default: return IndeterminateBoolean.YesAndNo; } } else { return base.ConvertFrom(context, culture, value); } } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(ToggleState)) { if (value is IndeterminateBoolean) { switch ((IndeterminateBoolean)value) { case IndeterminateBoolean.Yes: return ToggleState.On; case IndeterminateBoolean.No: return ToggleState.Off; case IndeterminateBoolean.YesAndNo: default: return ToggleState.Indeterminate; } } if (value is string) { switch (((string)value ?? string.Empty).Trim()) { case "Yes": return ToggleState.On; case "No": case "": return ToggleState.Off; case "Both": default: return ToggleState.Indeterminate; } } else { return base.ConvertTo(context, culture, value, destinationType); } } else { return base.ConvertTo(context, culture, value, destinationType); } } } Workaround: use the custom filtering functionality: http://docs.telerik.com/devtools/winforms/gridview/filtering/custom-filtering You can access the RadGridView.FilterDescriptors collection and according to the FilterDescriptor.Expression property to determine whether the row will be visible or not.
To reproduce: public Form1() { InitializeComponent(); BindingList<Item> items = new BindingList<Item>(); for (int i = 0; i < 30; i++) { if (i % 3 == 0) { items.Add(new Item(i,"Item" + i, IndeterminateBoolean.YesAndNo)); } else if (i % 3 == 1) { items.Add(new Item(i, "Item" + i, IndeterminateBoolean.Yes)); } else { items.Add(new Item(i, "Item" + i, IndeterminateBoolean.No)); } } this.radGridView1.DataSource = items; this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; this.radGridView1.EnableFiltering = true; this.radGridView1.ShowHeaderCellButtons = true; this.radGridView1.ShowFilteringRow = false; } public class Item { public int Id { get; set; } public string Name { get; set; } public IndeterminateBoolean IsActive { get; set; } public Item(int id, string name, IndeterminateBoolean isActive) { this.Id = id; this.Name = name; this.IsActive = isActive; } } public enum IndeterminateBoolean { No, Yes, YesAndNo } Workaround: use custom filtering http://docs.telerik.com/devtools/winforms/gridview/filtering/custom-filtering
To reproduce: Add the following view: for (int i = 0; i < 8; i++) { radGridView2.Columns.Add("Col" + (i+1)); } ColumnGroupsViewDefinition view = new ColumnGroupsViewDefinition(); view.ColumnGroups.Add(new GridViewColumnGroup("G1")); view.ColumnGroups.Add(new GridViewColumnGroup("G2")); view.ColumnGroups.Add(new GridViewColumnGroup("G3")); view.ColumnGroups[0].Rows.Add(new GridViewColumnGroupRow()); view.ColumnGroups[0].Rows[0].ColumnNames.Add("Col1"); view.ColumnGroups[0].Rows[0].ColumnNames.Add("Col2"); view.ColumnGroups[0].Rows[0].ColumnNames.Add("Col3"); view.ColumnGroups[1].Rows.Add(new GridViewColumnGroupRow()); view.ColumnGroups[1].Rows[0].ColumnNames.Add("Col4"); view.ColumnGroups[1].Rows[0].ColumnNames.Add("Col5"); view.ColumnGroups[2].Rows.Add(new GridViewColumnGroupRow()); view.ColumnGroups[2].Rows[0].ColumnNames.Add("Col6"); view.ColumnGroups[2].Rows[0].ColumnNames.Add("Col7"); view.ColumnGroups[2].Rows[0].ColumnNames.Add("Col8"); radGridView2.ViewDefinition = view; for (int i = 0; i < 10; i++) { radGridView2.Rows.Add("row"+i, "test","test","test","test","test","test"); } radGridView2.Columns[2].IsVisible = false; radGridView2.Columns[7].IsVisible = false; - Then export the grid with the spread exporter.
When the RadGridView.EnabledPaging property is set to true, the user should be allowed to specify not only the PageSize,but also the PagesCount for example. Afterwards, it would be convenient to have an event similar to RowSourceNeeded in order to load pages data on demand.
To reproduce: Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.RadGridView1.AutoGenerateColumns = False Dim column = New GridViewTextBoxColumn column.Name = "Name" column.FieldName = "ChildItem" column.DataType = GetType(CustomItem) column.DataTypeConverter = New CustomItemTypeConverter() Me.RadGridView1.Columns.Add(column) Me.RadGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill Dim objects = { New CustomContainer With {.ChildItem = New CustomItem With {.Name = "A"}}, New CustomContainer With {.ChildItem = New CustomItem With {.Name = "B"}}, New CustomContainer With {.ChildItem = New CustomItem With {.Name = "C"}} } Me.RadGridView1.DataSource = objects End Sub Private Sub RadGridView_EditorRequired(sender As Object, e As EditorRequiredEventArgs) Handles RadGridView1.EditorRequired e.EditorType = GetType(GridSpinEditor) End Sub Class CustomContainer Public Property ChildItem As CustomItem End Class Class CustomItem Public Property Name As String End Class Class CustomItemTypeConverter Inherits TypeConverter Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean If sourceType = GetType(Decimal) Then Return True End If Return MyBase.CanConvertFrom(context, sourceType) End Function Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean If destinationType = GetType(Decimal) OrElse destinationType = GetType(String) OrElse destinationType = GetType(CustomItem) Then Return True End If Return MyBase.CanConvertTo(context, destinationType) End Function Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, _ value As Object, destinationType As Type) As Object If TypeOf value Is CustomItem Then Dim customValue = DirectCast(value, CustomItem) If destinationType = GetType(Decimal) Then Return Microsoft.VisualBasic.AscW(customValue.Name.Chars(0)) ElseIf destinationType = GetType(String) Then Return customValue.Name ElseIf destinationType = GetType(CustomItem) Then Return customValue Else Return MyBase.ConvertTo(context, culture, value, destinationType) End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object) As Object If TypeOf value Is Decimal Then Dim decValue = DirectCast(value, Decimal) Dim intValue = CInt(decValue) Dim charValue = Microsoft.VisualBasic.ChrW(intValue) Return New CustomItem With {.Name = New String(charValue, 1)} End If Return MyBase.ConvertFrom(context, culture, value) End Function End Class Workaround: Public Class MyEditor Inherits GridSpinEditor Public Overrides ReadOnly Property IsModified() As Boolean Get If Me.originalValue Is Nothing Then Return (Me.Value IsNot Nothing AndAlso Me.Value <> DBNull.Value) End If If Me.Value Is Nothing Then Return (Me.originalValue IsNot Nothing AndAlso Me.originalValue <> DBNull.Value) End If Dim column As GridViewDataColumn = (DirectCast(Me.OwnerElement, GridDataCellElement)).ColumnInfo If column.DataTypeConverter IsNot Nothing AndAlso column.DataTypeConverter.CanConvertTo(Me.OwnerElement, GetType(Decimal)) Then Return Not column.DataTypeConverter.ConvertTo(Me.OwnerElement, column.FormatInfo, Me.originalValue, GetType(Decimal)).Equals(Convert.ToDecimal(Me.Value)) End If Return Not Convert.ToDecimal(Me.originalValue).Equals(Convert.ToDecimal(Me.Value)) End Get End Property End Class Private Sub RadGridView_EditorRequired(sender As Object, e As EditorRequiredEventArgs) Handles RadGridView1.EditorRequired e.EditorType = GetType(MyEditor) End Sub
To reproduce: - Add an expression column with nullable type as a data source. - Open the property builder. Workaround: Set the data type at run time.
If a dock window is focused programmatically, the RowValidating event is fired before selecting the new row by mouse cursor.
To reproduce: 1. Perform searching in the grid. 2. Group by a random column. 3. Navigating with next/previous buttons do not navigate the results in the displayed order. Workaround: set the EnablePaging property to false.
I've attached a sample project. Here are the steps to repeat this issue: 1. Run the application 2. Click column A and drag it to the right to reorder it, scrolling the window as it goes 3. You are eventually presented with a NullReferenceException You may have to try this several times with different columns before the problem manifests. I have found that moving just beyond the right edge of the main form and moving the mouse cursor up and down a little helps. I appears this problem only occurs in grids with many columns, so that fast scrolling can occur for multiple seconds when reordering columns. Workaround: Sub New() InitializeComponent() Me.RadGridView1.GridViewElement.RegisterService(New MyRadGridViewDragDropService(Me.RadGridView1.GridViewElement)) End Sub Public Class MyRadGridViewDragDropService Inherits RadGridViewDragDropService Public Sub New(gridViewElement As RadGridViewElement) MyBase.New(gridViewElement) End Sub Public Overrides ReadOnly Property Name As String Get Return "RadGridViewDragDropService" End Get End Property Protected Overrides Sub PrepareDragHint(dropTarget As Telerik.WinControls.ISupportDrop) Dim dragDropBehavior As IGridDragDropBehavior = Me.GetDragDropBehavior() If dragDropBehavior Is Nothing OrElse dragDropBehavior.DragHint Is Nothing _ OrElse dragDropBehavior.DragHint.Image Is Nothing Then Return End If Dim dropTargetItem As RadItem = TryCast(dropTarget, RadItem) If dropTargetItem IsNot Nothing AndAlso dropTargetItem.ElementTree IsNot Nothing _ AndAlso Not dropTargetItem.ElementTree.Control.Equals(Me.GridViewElement.ElementTree.Control) Then Return End If dragDropBehavior.UpdateDropContext(TryCast(Me.Context, ISupportDrag), dropTarget, Me.beginPoint) Dim hintSize As Size = dragDropBehavior.GetDragHintSize(dropTarget) Dim image As New Bitmap(hintSize.Width, hintSize.Height) Dim temp As Graphics = Graphics.FromImage(image) dragDropBehavior.DragHint.Paint(temp, New RectangleF(PointF.Empty, hintSize)) temp.Dispose() Dim dragHintWindow As New RadLayeredWindow() GetType(RadGridViewDragDropService).GetField("dragHintWindow", _ Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance).SetValue(Me, dragHintWindow) dragHintWindow.BackgroundImage = image End Sub End Class
To reproduce: - Add some columns to the grid, make sure that most of the columns are not visible (the user must scroll to view them). - Drag and drop the second column at the last position in the grid. - The result can be seen on the attached image. Workaround: Private Sub Columns_CollectionChanged(ByVal sender As Object, ByVal e As Telerik.WinControls.Data.NotifyCollectionChangedEventArgs) Me.RadGridView1.TableElement.ViewElement.UpdateRowsWhenColumnsChanged() End Sub
When scrolling to the bottom of the grid with the mouse, the last row is not lined up with the bottom of the grid. Also, when doing this, clicking on any row, leads to row jumping down to align properly, but a different row is selected. Workaround: public Form1() { InitializeComponent(); radGridView1.MouseDown+=radGridView1_MouseDown; radGridView1.MouseUp+=radGridView1_MouseUp; } bool scrolling = false; private void radGridView1_MouseDown(object sender, MouseEventArgs e) { ScrollBarThumb thumb = radGridView1.ElementTree.GetElementAtPoint(e.Location) as ScrollBarThumb; if (thumb != null) { scrolling = true; } } private void radGridView1_MouseUp(object sender, MouseEventArgs e) { if (scrolling) { scrolling = false; int scrollBarValue = radGridView1.TableElement.VScrollBar.Value; radGridView1.MasterTemplate.Refresh(); radGridView1.TableElement.VScrollBar.Value = scrollBarValue; } }
To reproduce: public abstract class Base { public abstract string Name { get; } } public class Child : Base { public override string Name { get { return "Child"; } } } public class Child2 : Base { public override string Name { get { return "Child2"; } } } public partial class RadForm1 : Telerik.WinControls.UI.RadForm { public RadForm1() { InitializeComponent(); var list = new List<Base>(); list.Add(new Child()); list.Add(new Child()); list.Add(new Child2()); radGridView1.DataSource = list.ToArray(); } } Workaround: radGridView1.DataSource = list;
When RadGridView is displaying a self-referencing it should be able to show the data with ColumnGroupsViewDefinition and HtmlViewDefinition.