Hi, Following to the workaroud (flag IsSearchAsync) provided (https://feedback.telerik.com/Project/154/Feedback/Details/245938-fix-radgridview-having-groups-filters-sort-descriptors-and-search-query-in-t), we discovered two issues : 1) the behavior of the grid is changed while using IsSearchAsync as true or false (see 2018-08-01_1849_DragDrop_behavior_with_IsSearchAsync.swf video attached). When set to true, the line found by the searchbox is automatically reselected. When the flag is set to false, it's not the case. 2) while playing with drag&drop, after some time the grid became unstable (see 2018-08-01_1847_-_dragdrop_issue_with_IsAsyncSearch.swf video attached). You can see that at the beginning, the D&D works fine. At 0:20 I can't select any line, and when I try to D&D, it drops always the same customer. At 0:40 you can see that even the SearchBox is broken and the progressbar is looping forever
Use attached to reproduce. Workaround: Set the TableHeaderHeight again after loading the layout.
To reproduce: please refer to the attached sample project and gif file
Workaround:
GridViewSpreadExport spreadExporter = new GridViewSpreadExport(this.radGridView1);
spreadExporter.ExportFormat = SpreadExportFormat.Pdf;
spreadExporter.ExportVisualSettings = true;
SpreadExportRenderer exportRenderer = new SpreadExportRenderer();
spreadExporter.RunExport(exportFile, exportRenderer);
Process.Start(exportFile);
To reproduce: run the attached project and toggle the checkbox in the header cell of the child template.
Workaround: use a custom GridCheckBoxHeaderCellElement
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
this.radGridView1.CreateCell += radGridView1_CreateCell;
DataTable dt = new DataTable();
dt.Columns.Add("CategoryId", typeof(int));
dt.Columns.Add("CategoryName", typeof(string));
dt.Columns.Add("ParentCategoryId", typeof(int));
dt.Rows.Add(1, "Category1", 0);
dt.Rows.Add(2, "Category2", 0);
dt.Rows.Add(3, "Category3", 0);
Random rand = new Random();
for (int i = 4; i < 20; i++)
{
dt.Rows.Add(i, "Category" + i, rand.Next(1, 4));
}
this.radGridView1.Relations.AddSelfReference(this.radGridView1.MasterTemplate, "CategoryId", "ParentCategoryId");
this.radGridView1.DataSource = dt;
this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;
GridViewTemplate childTemplate = CreateChildTemplate();
GridViewRelation relation = new GridViewRelation(
this.radGridView1.MasterTemplate,
childTemplate);
relation.ChildColumnNames.Add("CategoryId");
relation.ParentColumnNames.Add("CategoryId");
this.radGridView1.Relations.Add(relation);
}
private void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
{
if (e.CellType == typeof(GridCheckBoxHeaderCellElement))
{
e.CellElement = new CustomGridCheckBoxHeaderCellElement(e.Column, e.Row);
}
}
private GridViewTemplate CreateChildTemplate()
{
GridViewTemplate childTemplate = new GridViewTemplate();
childTemplate.AutoGenerateColumns = false;
this.radGridView1.Templates.Add(childTemplate);
GridViewDecimalColumn decColumn = new GridViewDecimalColumn
{
Name = "CategoryId",
HeaderText = "CategoryId Id",
FieldName = "CategoryId",
IsVisible = false,
MinWidth = 100
};
childTemplate.Columns.Add(decColumn);
GridViewTextBoxColumn tbxColumn = new GridViewTextBoxColumn
{
Name = "RightName",
HeaderText = "Right Name",
FieldName = "RGT_NAME",
ReadOnly = true,
MinWidth = 100
};
childTemplate.Columns.Add(tbxColumn);
GridViewCheckBoxColumn chkxColumn = new GridViewCheckBoxColumn
{
Name = "Checkbox",
EnableHeaderCheckBox = true,
FieldName = "HasAccess",
};
childTemplate.Columns.Add(chkxColumn);
childTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
return childTemplate;
}
public class CustomGridCheckBoxHeaderCellElement : GridCheckBoxHeaderCellElement
{
public CustomGridCheckBoxHeaderCellElement(GridViewColumn column, GridRowElement row) : base(column, row)
{
}
public bool SuspendProcessingToggleStateChanged
{
get
{
FieldInfo fi = typeof(GridCheckBoxHeaderCellElement).GetField("suspendProcessingToggleStateChanged", BindingFlags.NonPublic | BindingFlags.Instance);
return (bool)fi.GetValue(this);
}
set
{
FieldInfo fi = typeof(GridCheckBoxHeaderCellElement).GetField("suspendProcessingToggleStateChanged", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(this, value);
}
}
public bool ShouldCheckDataRows
{
get
{
FieldInfo fi = typeof(GridCheckBoxHeaderCellElement).GetField("shouldCheckDataRows", BindingFlags.NonPublic | BindingFlags.Instance);
return (bool)fi.GetValue(this);
}
set
{
FieldInfo fi = typeof(GridCheckBoxHeaderCellElement).GetField("shouldCheckDataRows", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(this, value);
}
}
protected override void checkbox_ToggleStateChanged(object sender, StateChangedEventArgs args)
{
if (SuspendProcessingToggleStateChanged)
{
return;
}
if (this.ViewTemplate != null && !this.ViewTemplate.IsSelfReference && !this.MasterTemplate.IsSelfReference)
{
this.MasterTemplate.BeginUpdate();
}
else
{
this.TableElement.BeginUpdate();
}
object valueState = DBNull.Value;
if (args.ToggleState == ToggleState.On)
{
valueState = true;
}
else if (args.ToggleState == ToggleState.Off)
{
valueState = false;
}
else if (args.ToggleState == ToggleState.Indeterminate)
{
valueState = null;
}
RaiseToggleStateEvent();
if (!ShouldCheckDataRows)
{
if (this.ViewTemplate != null && !this.ViewTemplate.IsSelfReference && !this.MasterTemplate.IsSelfReference)
{
this.MasterTemplate.EndUpdate(true, new DataViewChangedEventArgs(ViewChangedAction.DataChanged));
}
return;
}
this.GridViewElement.EditorManager.EndEdit();
this.TableElement.BeginUpdate();
this.MasterTemplate.MasterViewInfo.TableSearchRow.SuspendSearch();
List<GridViewRowInfo> list = GetRowsToIterateOver();
foreach (GridViewRowInfo rowInfo in list)
{
GridViewGroupRowInfo groupRow = rowInfo as GridViewGroupRowInfo;
if (groupRow != null)
{
this.CheckAllCheckBoxInChildRows(groupRow, valueState);
}
else
{
rowInfo.Cells[this.ColumnIndex].Value = valueState;
}
}
this.MasterTemplate.MasterViewInfo.TableSearchRow.ResumeSearch();
this.TableElement.EndUpdate(false);
if (this.ViewTemplate != null && !this.ViewTemplate.IsSelfReference && !this.MasterTemplate.IsSelfReference)
{
this.MasterTemplate.EndUpdate(true, new DataViewChangedEventArgs(ViewChangedAction.DataChanged));
}
else
{
this.TableElement.EndUpdate(false);
}
this.TableElement.Update(GridUINotifyAction.DataChanged);
}
private void CheckAllCheckBoxInChildRows(GridViewGroupRowInfo row, object state)
{
List<GridViewRowInfo> list = new List<GridViewRowInfo>();
foreach (GridViewRowInfo rowInfo in row.ChildRows)
{
list.Add(rowInfo);
}
foreach (GridViewRowInfo rowInfo in list)
{
GridViewGroupRowInfo groupInfo = rowInfo as GridViewGroupRowInfo;
if (groupInfo != null)
{
this.CheckAllCheckBoxInChildRows(groupInfo, state);
}
else
{
rowInfo.Cells[this.ColumnIndex].Value = state;
}
}
}
private List<GridViewRowInfo> GetRowsToIterateOver()
{
if (this.ViewTemplate != null && this.ViewTemplate.IsSelfReference)
{
PrintGridTraverser traverser = new PrintGridTraverser(this.ViewInfo);
List<GridViewRowInfo> result = new List<GridViewRowInfo>();
while (traverser.MoveNext())
{
if (traverser.Current is GridViewDataRowInfo)
{
result.Add(traverser.Current);
}
}
return result;
}
return new List<GridViewRowInfo>(this.ViewInfo.Rows);
}
}
}
Hello,
In our Environment it's not possible to assign a GroupComparer to another GridView template then MasterTemplate. The GroupComparer property is always null after assignment.
It's possible to assign our custom comparer to the MasterTemplate and it will be triggered, but not in another template then MasterTemplate.
Best regards.
Tassilo Koller | Dipl. Informatiker (FH) | IT-Softwareentwicklung
[T] +49 (0)8233 381 383
[E] Tassilo.Koller@forum-media.com | [W] www.forum-verlag.com
FORUM MEDIA GROUP GMBH| Mandichostraße 18 | 86504 Merching | [T] +49 (0)8233 381-0 | [F] + 49 (0)8233 381-222 | [W] www.forum-media.com| Sitz der Gesellschaft: Merching | Register: AG Augsburg HRB 11537 | Geschäftsführer: Magdalena Balanicka, Norbert Bietsch, Roland Hradek, Mihaela Mravlje | Beirat: Ronald Herkert (Vorsitzender)
Elektronische Rechnungen bitte an folgende Adresse senden: invoice@forum-media.com
Steps to reproduce:
This happens after calling RunExport.
I attached a gif and a sample project.
June 19, 2019
I have implemented this and it is exactly what I want and need, Thank you!
However I thought I might point out that when you tab out it doesn't implement the search, only when you press enter.
And when you press the X to clear the search it clears the text box but not the search. the count of found and the highlighted finds remain
In my gridview need support of different heights of rows. I solved it with the autosize property.
But now I have a side action that the header row and filter row also react to the autosize property.
Attached you can see this behaviour...
Here my code:
Grid.MasterView.TableFilteringRow.MinHeight = 40
Grid.AutoSizeRows = True
Is there a chance to separate data rows from filter and header row?
Regards,
Dimitri
To reproduce:
- Set the AutoSize to true
- Add GroupDescriptor
- An InvalidOperationException is thrown
To reproduce:
Sub New()
InitializeComponent()
Dim dt1 As New DataTable
dt1.Columns.Add("Id", GetType(Integer))
dt1.Columns.Add("Name", GetType(String))
For index = 1 To 20
dt1.Rows.Add(index, "Parent" & index)
Next
Me.RadGridView1.MasterTemplate.DataSource = dt1
Me.RadGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
Dim dt2 As New DataTable
dt2.Columns.Add("Id", GetType(Integer))
dt2.Columns.Add("Name", GetType(String))
dt2.Columns.Add("ParentId", GetType(Integer))
Dim dt3 As New DataTable
dt3.Columns.Add("Id", GetType(Integer))
dt3.Columns.Add("Name", GetType(String))
dt3.Columns.Add("ParentId", GetType(Integer))
For index = 1 To 20
If index Mod 2 = 0 Then
dt2.Rows.Add(index, "Child1." & index, index)
If index Mod 4 = 0 Then
dt3.Rows.Add(index, "Child2." & index, index)
End If
ElseIf index Mod 3 = 0 Then
dt3.Rows.Add(index, "Child2." & index, index)
Else
dt3.Rows.Add(index, "Child2." & index, index)
End If
Next
Dim template As New GridViewTemplate()
template.DataSource = dt2
template.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
RadGridView1.MasterTemplate.Templates.Add(template)
Dim relation As New GridViewRelation(RadGridView1.MasterTemplate)
relation.ChildTemplate = template
relation.RelationName = "FirstChild"
relation.ParentColumnNames.Add("Id")
relation.ChildColumnNames.Add("ParentId")
RadGridView1.Relations.Add(relation)
Dim template2 As New GridViewTemplate()
template2.DataSource = dt3
template2.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
RadGridView1.MasterTemplate.Templates.Add(template2)
Dim relation2 As New GridViewRelation(RadGridView1.MasterTemplate)
relation2.ChildTemplate = template2
relation2.RelationName = "SecondChild"
relation2.ParentColumnNames.Add("Id")
relation2.ChildColumnNames.Add("ParentId")
RadGridView1.Relations.Add(relation2)
AddHandler Me.RadGridView1.ChildViewExpanding, AddressOf ChildViewExpanding
End Sub
Private Sub RadGridView1_ViewCellFormatting(sender As Object, e As Telerik.WinControls.UI.CellFormattingEventArgs) _
Handles RadGridView1.ViewCellFormatting
Dim cell As GridDetailViewCellElement = TryCast(e.CellElement, GridDetailViewCellElement)
Dim expanderCell As GridGroupExpanderCellElement = TryCast(e.CellElement, GridGroupExpanderCellElement)
If expanderCell IsNot Nothing AndAlso TypeOf e.CellElement.RowElement Is GridDataRowElement Then
Dim hierarchyRow As GridViewHierarchyRowInfo = DirectCast(expanderCell.RowInfo, GridViewHierarchyRowInfo)
If Not IsExpandable(hierarchyRow) Then
expanderCell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Hidden
Else
expanderCell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Visible
End If
ElseIf cell IsNot Nothing Then
Dim hierarchyRow As GridViewHierarchyRowInfo = DirectCast(DirectCast(cell.RowInfo, GridViewDetailsRowInfo).Owner, _
GridViewHierarchyRowInfo)
For i As Integer = 0 To cell.PageViewElement.Items.Count - 1
Dim item As RadPageViewItem = cell.PageViewElement.Items(i)
Dim viewInfo As GridViewInfo = hierarchyRow.Views(i)
item.Text = "Child Template " & i
If viewInfo.ChildRows.Count = 0 Then
If i = 0 AndAlso i < cell.PageViewElement.Items.Count - 1 Then
cell.PageViewElement.Items(i + 1).IsSelected = True
End If
item.Visibility = Telerik.WinControls.ElementVisibility.Hidden
Else
item.Visibility = Telerik.WinControls.ElementVisibility.Visible
End If
Next
End If
End Sub
Private Function IsExpandable(hierarchyRow As GridViewHierarchyRowInfo) As Boolean
For Each view As GridViewInfo In hierarchyRow.Views
If view.ChildRows.Count > 0 Then
Return True
End If
Next
Return False
End Function
Workaround:
AddHandler Me.RadGridView1.ChildViewExpanding, AddressOf RadGridView1_ChildViewExpanding
AddHandler Me.RadGridView1.MouseDown, AddressOf RadGridView_MouseDown
Private Sub RadGridView1_ChildViewExpanding(sender As Object, e As ChildViewExpandingEventArgs)
If lastClicked IsNot Nothing AndAlso e.ParentRow.Equals(lastClicked) Then
e.Cancel = False
Else
e.Cancel = True
End If
End Sub
Dim lastClicked As GridViewRowInfo
Private Sub RadGridView_MouseDown(sender As Object, e As MouseEventArgs)
Dim expander As GridExpanderItem = TryCast(Me.RadGridView1.ElementTree.GetElementAtPoint(e.Location), GridExpanderItem)
If expander IsNot Nothing Then
lastClicked = DirectCast(expander.Parent, GridGroupExpanderCellElement).RowInfo
End If
End Sub
To reproduce: - Add a checkbox column and hide some of the cells. - Change some values and then click on empty cell. - Exception occurs in OnMouseDownLeft method (GridRowBeahvior class) Workaround: Hide the checkbox only.
To reproduce:
1. Add a RadMultiColumnComboBox and populate it with data.
2. Set the DropDownStyle property of the control to DropDownList
3. Set the EditorControl.AllowSearchRow and the AutoSizeDropDownToBestFit properties to true .
4. When you open the drop down and try to use the search row (e.g. clicking over the arrow buttons), the drop down is closed.
Workaround:
public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
public RadForm1()
{
InitializeComponent();
this.radMultiColumnComboBox1.EditorControl.AllowSearchRow = true;
this.radMultiColumnComboBox1.DropDownStyle = Telerik.WinControls.RadDropDownStyle.DropDownList;
this.radMultiColumnComboBox1.DropDownClosing += RadMultiColumnComboBox1_DropDownClosing;
}
private void RadMultiColumnComboBox1_DropDownClosing(object sender, RadPopupClosingEventArgs args)
{
Point position = this.radMultiColumnComboBox1.EditorControl.PointToClient(Cursor.Position);
Telerik.WinControls.RadElement searchElement = this.radMultiColumnComboBox1.EditorControl.ElementTree.GetElementAtPoint(position);
if (searchElement != null)
{
GridSearchCellElement parent = searchElement.FindAncestor<GridSearchCellElement>();
if (parent != null)
{
args.Cancel = true;
}
}
}
}
1. Create a new project and setup hierarchy 2. Add a large number of rows as child rows to the last row at first level 3. Run the project and try to expand the last row
- Create a new project containing RadGridView - Build hierarchy with large text data in cells - Set the AutoSizeRows property to true and AutoSizeColumnMode to Fill - Run the project, scroll down and try to click on a cell
I have the following logic for my View, which has a RadGridView control (add to form at design-time).
GUI is a lightweight view, Controller does the heavy lifting. That part is all good.
However setting the column name and column autosize stuff is a little more "over-complicated" than I'd wish to see. It all works though.
Would be nice to have a "GridViewTextBoxColumnAttribute" as per below, for properties on Custom datasource objects to achieve the same thing in a more concise way.
Or am I missing something and there is a much easier way to do what I want?
I have a number of datasource classes: MyObject, MyCar, MyDog, MyWhatever... that ALL have different property names and datatypes, but may or may-not have the same column name or MasterTemplate style.
Also BestFitColumns is a function of the MasterTemplate, would be nice if it were a property for consistency sake (call to internal function encapsulated in the Set etc), as from a Telerik user's perspective it's just an enum. Then it would be setable in the SmartTag window as well, as functions can't be assigned to.
public partial class RadForm1 : Telerik.WinControls.UI.RadForm, IView
{
public RadForm1)
{
InitializeComponent();
}
private void RadForm1_Load(object sender, EventArgs e)
{
var x = new Controller();
x.SetTemplate(this);
}
public Telerik.WinControls.UI.RadGridView RadGridView()
{
return this.radGridView1;
}
}
public class Controller
{
public void SetTemplate(IView view)
{
var View_RadGrid = view.RadGridView();
View_RadGrid.MasterTemplate.AutoGenerateColumns = false;
View_RadGrid.MasterTemplate.AutoGenerateHierarchy = false;
View_RadGrid.MasterTemplate.AllowColumnResize = false;
View_RadGrid.MasterTemplate.BestFitColumns(Telerik.WinControls.UI.BestFitColumnMode.AllCells);
var cols = new List<Telerik.WinControls.UI.GridViewDataColumn>()
{
new Telerik.WinControls.UI.GridViewTextBoxColumn("DisplayName1"),
new Telerik.WinControls.UI.GridViewTextBoxColumn("DisplayName2")
};
View_RadGrid.MasterTemplate.Columns.AddRange(cols.ToArray());
View_RadGrid.DataSource = new List<MyObject>()
{
new MyObject() { DisplayName1 = "1", DisplayName2 = "2" },
new MyObject() { DisplayName1 = "3", DisplayName2 = "4" }
};
}
private class MyObject
{
[GridViewTextBoxColumnAttribute("DisplayName1", BestFitColumn = Telerik.WinControls.UI.BestFitColumnMode.AllCells, AllowColumnResize = false)]
public string DisplayName1 { get; set; }
[GridViewTextBoxColumnAttribute("DisplayName2", BestFitColumn = Telerik.WinControls.UI.BestFitColumnMode.AllCells, AllowColumnResize = false)]
public string DisplayName2 { get; set; }
}
}
public interface IView
{
Telerik.WinControls.UI.RadGridView RadGridView();
}
[System.AttributeUsage(System.AttributeTargets.Property)]
public class GridViewTextBoxColumnAttribute : System.Attribute
{
private string FieldName;
public Telerik.WinControls.UI.BestFitColumnMode BestFitColumn;
public bool AllowColumnResize;
public GridViewTextBoxColumnAttribute(string fieldName)
{
this.FieldName = fieldName;
}
}