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:
private void Form1_Load(object sender, EventArgs e)
{
this.productsTableAdapter.Fill(this.nwindDataSet.Products);
this.categoriesTableAdapter.Fill(this.nwindDataSet.Categories);
this.radGridView1.AutoGenerateColumns = false;
this.radGridView1.DataSource = this.productsBindingSource;
GridViewComboBoxColumn col = new GridViewComboBoxColumn();
col.DataSource = this.categoriesBindingSource;
col.MinWidth = 200;
col.DisplayMember = "Description";
col.ValueMember = "CategoryID";
this.radGridView1.Columns.Add(col);
this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
this.radGridView1.CellValueChanged += radGridView1_CellValueChanged;
}
private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
{
string value = "{nothing}";
if (e.Value != null)
{
value = Convert.ToString(e.Value);
}
RadMessageBox.Show("CellValueChanged. Value >> " + value);
}
Note: if the cell value is not null, the CellValueChanged event is not fired when the selection in drop down is not changed.
Additional scenario: if you use a RadMultiColumnComboBoxElement for this column replaced in the EditorRequired, the issue is reproducible again.
The event should be used to cancel copying for a single cell or override the value to be copied to the Clipboard.
To reproduce:
public Form1()
{
InitializeComponent();
List<Item> items = new List<Item>();
for (int i = 0; i < 10; i++)
{
items.Add(new Item(i,"Item" + i,Color.Red));
}
this.radGridView1.DataSource = items;
this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;
this.radGridView1.CellValidating += radGridView1_CellValidating;
}
private void radGridView1_CellValidating(object sender, Telerik.WinControls.UI.CellValidatingEventArgs e)
{
if (e.ActiveEditor != null && e.ActiveEditor is GridColorPickerEditor)
{
Color c = (Color)e.Value;
if (c == Color.Red)
{
e.Cancel = true;
Console.WriteLine("Red is not allowed!");
}
}
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public Color Color { get; set; }
public Item(int id, string name, Color color)
{
this.Id = id;
this.Name = name;
this.Color = color;
}
}
Steps:
1. Activate the editor for the Color cell.
2. Leave the color as it
3. Press the Enter key. The CellValidating event is fired twice.
Note: it seems that when the color text is selected, the event is fired twice.
How to reproduce:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.radGridView1.DataSource = this.GetSampleData();
this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
this.radGridView1.EnableFiltering = true;
this.radGridView1.ShowFilteringRow = false;
this.radGridView1.ShowHeaderCellButtons = true;
}
private DataTable GetSampleData()
{
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(double));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("IsValid", typeof(bool));
dt.Columns.Add("Date", typeof(DateTime));
for (int i = 0; i < 115; i++)
{
dt.Rows.Add(((double)i * 5 / 7) * 3, "Name " + i, i % 2 == 0, DateTime.Now.AddDays(i));
}
return dt;
}
}
Workaround specify decimal as the type of the column in the DataTable object or clone the DataTAble object and change the type of the column:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataTable dt = this.GetSampleData();
DataTable dtCloned = dt.Clone();
dtCloned.Columns[0].DataType = typeof(decimal);
foreach (DataRow row in dt.Rows)
{
dtCloned.ImportRow(row);
}
this.radGridView1.DataSource = dtCloned;
this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
this.radGridView1.EnableFiltering = true;
this.radGridView1.ShowFilteringRow = false;
this.radGridView1.ShowHeaderCellButtons = true;
}
private DataTable GetSampleData()
{
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(double));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("IsValid", typeof(bool));
dt.Columns.Add("Date", typeof(DateTime));
for (int i = 0; i < 115; i++)
{
dt.Rows.Add(((double)i * 5 / 7) * 3, "Name " + i, i % 2 == 0, DateTime.Now.AddDays(i));
}
return dt;
}
}
To reproduce:
- Add DateTime column and set the RowHeight to 20.
- Set the theme to Windows7.
- The text is not visible when the editor is shown.
Workaround:
private void RadGridView2_CellEditorInitialized(object sender, GridViewCellEventArgs e)
{
RadDateTimeEditor editor = e.ActiveEditor as RadDateTimeEditor;
if (editor != null)
{
var element = editor.EditorElement as RadDateTimeEditorElement;
element.Font = new Font("Segoe UI", 8, FontStyle.Regular);
element.Children[1].Visibility = ElementVisibility.Collapsed;
element.TextBoxElement.ShowBorder = false;
element.TextBoxElement.TextBoxItem.HostedControl.MinimumSize = new Size(0, 12);
}
}
Steps to reproduce: - create a winforms project - create form (normal windows form, not telerik form) - create radgridview from toolbox - right click and open property builder - select mastertemplate - set viewdefinition = columngroups view - add 3-4 columns (textbox, combobox, etc...) - click ok button at the property builder - right click on the radgridview and open the property builder - rename the name and the header text of the first column - click ok button at the property builder
To reproduce: use the following code snippet and enter in the filter row one of the row values as it is shown in the screenshot:
this.radGridView1.EnableFiltering = true;
GridViewDateTimeColumn dateTimeColumn = new GridViewDateTimeColumn("DateTimeColumn");
dateTimeColumn.Format = DateTimePickerFormat.Custom;
dateTimeColumn.CustomFormat = "dd/MM/yyyy HH:mm:ss";
radGridView1.MasterTemplate.Columns.Add(dateTimeColumn);
this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
for (int i = 0; i < 10; i++)
{
this.radGridView1.Rows.Add(DateTime.Now.AddDays(i));
}
Workaround: custom filtering: http://docs.telerik.com/devtools/winforms/gridview/filtering/custom-filtering
To reproduce:
public class CustomGridViewCheckBoxColumn : GridViewCheckBoxColumn
{
}
CustomGridViewCheckBoxColumn col = new CustomGridViewCheckBoxColumn();
this.radGridView1.Columns.Add(col);
this.radGridView1.EnableFiltering = true;
1. Click the filter button and select "Custom"
2. Close the dialog.
Workaround:
this.radGridView1.CreateCompositeFilterDialog += radGridView1_CreateCompositeFilterDialog;
private void radGridView1_CreateCompositeFilterDialog(object sender, GridViewCreateCompositeFilterDialogEventArgs e)
{
e.Dialog = new CustomCompositeFilterForm();
}
public class CustomCompositeFilterForm : CompositeFilterForm
{
public override void Initialize(GridViewDataColumn dataColumn, FilterDescriptor filterDescriptor, bool useTypedEditors)
{
base.Initialize(dataColumn, filterDescriptor, useTypedEditors);
if (dataColumn is GridViewCheckBoxColumn)
{
RadGroupBox groupBox = this.Controls[0] as RadGroupBox;
groupBox.Controls.Remove(this.RightEditor);
groupBox.Controls.Remove(this.LeftEditor);
MethodInfo mi = typeof(CompositeFilterForm).GetMethod("InitializeCheckBoxEditors", BindingFlags.Instance | BindingFlags.NonPublic);
mi.Invoke(this, null);
}
}
}
Please refer to the attached sample project.
To reproduce: please refer to the attached sample project.
1. Edit the CommonInt property for the first child row.
2. Edit the CommonInt property for the second child row.
Workaround: Add the grid programmatically at run time.
Second Workaround:
this.radGridView1.CellValueChanged+=radGridView1_CellValueChanged;
private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
{
e.Column.OwnerTemplate.Refresh(e.Column);
}
To reproduce: - Bind the grid to progress binding source at design time. - Locate GroupDescriptors in Properties and click the ellipsis button to open the GroupDescriptor Collection Editor. - Click Add and select the new item. - Select the GroupNames collection to open the SortDescriptor Collection Editor. - Click Add. - An exception is thrown and the UI freezes. Workaround: Add descriptors at runime.
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);
}
}
To reproduce:
- Bind the grid and reset its data source in the CellValueChanged event handler.
- Start the application, click in a cell, delete the contents and right click a header cell.
- Exception is thrown.
Workaround:
class MyGridHeaderCellElement : GridHeaderCellElement
{
public MyGridHeaderCellElement(GridViewColumn col, GridRowElement row) : base(col, row)
{ }
protected override Type ThemeEffectiveType
{
get
{
return typeof(GridHeaderCellElement);
}
}
protected override void ShowContextMenu()
{
if (this.ViewTemplate != null)
{
base.ShowContextMenu();
}
}
}
private void RadGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
{
if (e.CellType == typeof(GridHeaderCellElement))
{
e.CellType = typeof(MyGridHeaderCellElement);
}
}
To reproduce:
DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
dt.Columns.Add("Id");
dt.Columns.Add("Name");
dt.Columns.Add("Type");
for (int i = 0; i < 30; i++)
{
dt.Rows.Add(i, "Item" + i, "Type" + i % 2);
}
this.radGridView1.DataSource = dt;
this.radGridView1.AutoExpandGroups = true;
GroupDescriptor descriptor = new GroupDescriptor();
descriptor.GroupNames.Add("Type", ListSortDirection.Ascending);
this.radGridView1.GroupDescriptors.Add(descriptor);
}
private void button1_Click(object sender, EventArgs e)
{
dt.Rows.Add(30, "Item30", "Type3");
}
Workaround: set the AutoExpandGroups property to false and manually expand the groups when a new row is added.
To reproduce: please refer to the attached gif file demonstrating how to reproduce the issue with the Demo application. Workaround: use the basic filtering.
Add an ExportToXlsx option into the native RadGridView exporting. It has been done for WPF (http://docs.telerik.com/devtools/wpf/controls/radgridview/export/export-xlsx) - why not WinForms. This would avoid the pain of having to implement the export using RadSpreadProcessing.
To reproduce:
Open the attached project, select two rows and delete them.
Workaround:
private void RadGridView1_RowValidating(object sender, Telerik.WinControls.UI.RowValidatingEventArgs e)
{
if (e.RowIndex != -1)
{
}
}
To reproduce: populate RadGridView with data and use the following code snippet:
Me.RadGridView1.TableElement.TableHeaderHeight = 60
RadGridView1.PrintPreview()
Workaround:
Private Sub RadButton1_Click(sender As Object, e As EventArgs) Handles RadButton1.Click
Me.RadGridView1.TableElement.TableHeaderHeight = 60
Dim printStyle As GridPrintStyle = New GridPrintStyle(RadGridView1)
Dim renderer As CustomTableViewDefinitionPrintRenderer = New CustomTableViewDefinitionPrintRenderer(RadGridView1)
printStyle.PrintRenderer = renderer
RadGridView1.PrintStyle = printStyle
RadGridView1.PrintPreview()
End Sub
Public Class CustomTableViewDefinitionPrintRenderer
Inherits TableViewDefinitionPrintRenderer
Public Sub New(grid As RadGridView)
MyBase.New(grid)
End Sub
Private Function GetRowLayout(row As GridViewRowInfo, fitWidthMode As PrintFitWidthMode, _
hierarchyIndent As Integer, drawArea As Rectangle) As TableViewRowLayout
Dim hashKey As Integer = row.ViewTemplate.GetHashCode() + row.HierarchyLevel
Dim fi As FieldInfo = GetType(TableViewDefinitionPrintRenderer).GetField("rowLayouts", BindingFlags.NonPublic Or BindingFlags.Instance)
Dim rowLayouts As Dictionary(Of Integer, TableViewRowLayout) = fi.GetValue(Me)
If rowLayouts.ContainsKey(hashKey) Then
Return rowLayouts(hashKey)
End If
Dim table As GridTableElement = TryCast(row.ViewTemplate.ViewDefinition.CreateViewUIElement(row.ViewInfo), GridTableElement)
table.Initialize(Me.GridView.GridViewElement, row.ViewInfo)
table.RowHeight = Me.GridView.TableElement.RowHeight
table.TableHeaderHeight = Me.GridView.TableElement.TableHeaderHeight
Me.GridView.ElementTree.ApplyThemeToElement(table)
Dim rowLayout As New TableViewRowLayout()
rowLayout.Context = GridLayoutContext.Printer
rowLayout.Initialize(table)
Dim systemWidth As Integer = 0
For Each c As GridViewColumn In rowLayout.RenderColumns
If TypeOf c Is GridViewRowHeaderColumn OrElse TypeOf c Is GridViewIndentColumn Then
systemWidth += rowLayout.GetColumnWidth(c)
End If
Next
Me.GridView.BeginUpdate()
Dim mode As GridViewAutoSizeColumnsMode = rowLayout.ViewTemplate.AutoSizeColumnsMode
If fitWidthMode = PrintFitWidthMode.FitPageWidth Then
Dim state As ColumnsState = Me.SaveColumnsState(rowLayout.ViewTemplate)
rowLayout.ViewTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
Dim groupLevel As Integer = If(row.Group IsNot Nothing, row.Group.Level + 1, 0)
rowLayout.MeasureRow(New SizeF(drawArea.Width + systemWidth - ((row.HierarchyLevel - groupLevel) * hierarchyIndent), drawArea.Height))
Me.RestoreColumnsState(state)
Else
rowLayout.ViewTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.None
rowLayout.MeasureRow(New SizeF(Me.GridView.Width, Me.GridView.Height))
End If
rowLayout.ViewTemplate.AutoSizeColumnsMode = mode
Me.GridView.EndUpdate(False)
rowLayouts.Add(hashKey, rowLayout)
Return rowLayout
End Function
Public Overrides Sub DrawPage(traverser As PrintGridTraverser, drawArea As Rectangle, _
graphics As Graphics, settings As GridPrintSettings, pageNumber As Integer)
Dim fi As FieldInfo = GetType(TableViewDefinitionPrintRenderer).GetField("currentPage", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim currentPage As Integer = fi.GetValue(Me)
Dim skipPage As Boolean = currentPage <> pageNumber
Dim drawAreaHeight As Integer = drawArea.Height
Dim currentX As Integer = drawArea.X
Dim currentY As Integer = drawArea.Y
Dim rowLayout As TableViewRowLayout = Me.GetRowLayout(Me.GridView.MasterView.TableHeaderRow, _
settings.FitWidthMode, settings.HierarchyIndent, drawArea)
rowLayout.IgnoreColumnVisibility = settings.PrintHiddenColumns
Dim systemWidth As Integer = 0
For Each c As GridViewColumn In rowLayout.RenderColumns
If TypeOf c Is GridViewRowHeaderColumn OrElse TypeOf c Is GridViewIndentColumn Then
systemWidth += rowLayout.GetColumnWidth(c)
End If
Next
Dim rowWidth As Integer = CInt(rowLayout.DesiredSize.Width) - systemWidth
If settings.FitWidthMode = PrintFitWidthMode.NoFitCentered Then
currentX += ((drawArea.Width - rowWidth) / 2)
End If
Dim fi2 As FieldInfo = GetType(TableViewDefinitionPrintRenderer).GetField("firstPage", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim firstPage As Integer = fi2.GetValue(Me)
If ((Me.GridView.ShowColumnHeaders AndAlso (firstPage AndAlso pageNumber = 1)) OrElse settings.PrintHeaderOnEachPage) _
AndAlso Not settings.PrintHierarchy Then
Me.PrintRow(Me.GridView.MasterView.TableHeaderRow, rowLayout, settings, currentX, currentY, graphics, _
drawArea)
Dim rowHeight As Integer = Me.GetDataRowHeight(Me.GridView.MasterView.TableHeaderRow, rowLayout) + Me.GridView.TableElement.RowSpacing
currentY += rowHeight
drawAreaHeight -= rowHeight
End If
fi2.SetValue(Me, False)
Dim skipPageCurrentY As Integer = currentY
Dim row As GridViewRowInfo = Nothing
If Me.PrintPages.Count > 0 AndAlso Not settings.PrintHierarchy Then
row = traverser.Current
End If
Dim firstRow As Boolean = True
While traverser.MoveNext()
If Not (TypeOf traverser.Current Is GridViewDataRowInfo OrElse TypeOf traverser.Current Is GridViewGroupRowInfo OrElse _
TypeOf traverser.Current Is GridViewSummaryRowInfo OrElse (TypeOf traverser.Current Is GridViewTableHeaderRowInfo _
AndAlso settings.PrintHierarchy)) Then
Continue While
End If
Dim hierarchyRow As GridViewHierarchyRowInfo = TryCast(traverser.Current, GridViewHierarchyRowInfo)
If hierarchyRow IsNot Nothing AndAlso hierarchyRow.Views.Count > 0 Then
Select Case settings.ChildViewPrintMode
Case ChildViewPrintMode.PrintFirstView
hierarchyRow.ActiveView = hierarchyRow.Views(0)
Exit Select
Case ChildViewPrintMode.PrintCurrentlyActiveView
'Do nothing the view is already selected
Exit Select
Case ChildViewPrintMode.SelectViewToPrint
Dim e As New ChildViewPrintingEventArgs(hierarchyRow.Views.IndexOf(hierarchyRow.ActiveView), hierarchyRow)
Me.OnChildViewPrinting(e)
hierarchyRow.ActiveView = hierarchyRow.Views(e.ActiveViewIndex)
Exit Select
End Select
End If
rowLayout = Me.GetRowLayout(traverser.Current, settings.FitWidthMode, settings.HierarchyIndent, drawArea)
Dim rowHeight As Integer = 0
If TypeOf traverser.Current Is GridViewGroupRowInfo Then
rowHeight = Me.GetRowSize(traverser.Current, rowLayout).Height
Else
rowHeight = Me.GetDataRowHeight(traverser.Current, rowLayout)
End If
If (currentY + rowHeight >= drawArea.Bottom OrElse skipPageCurrentY + rowHeight >= drawArea.Bottom) AndAlso Not firstRow Then
traverser.MovePrevious()
skipPageCurrentY = currentY
skipPage = currentPage <> pageNumber
fi.SetValue(Me, currentPage + 1)
If skipPage Then
Continue While
Else
Exit While
End If
End If
If TypeOf traverser.Current Is GridViewGroupRowInfo Then
If settings.PrintGrouping Then
If currentPage = pageNumber Then
Me.PrintRowWideCell(traverser.Current, rowLayout, settings, currentX, currentY, graphics)
currentY += rowHeight + Me.GridView.TableElement.RowSpacing
Else
skipPageCurrentY += rowHeight + Me.GridView.TableElement.RowSpacing
End If
End If
Else
If TypeOf traverser.Current Is GridViewSummaryRowInfo AndAlso Not settings.PrintSummaries Then
Continue While
End If
If currentPage = pageNumber Then
Me.PrintRow(traverser.Current, rowLayout, settings, currentX, currentY, graphics, _
drawArea)
currentY += rowHeight + Me.GridView.TableElement.RowSpacing
Else
skipPageCurrentY += rowHeight + Me.GridView.TableElement.RowSpacing
End If
End If
If drawAreaHeight < rowHeight AndAlso firstRow Then
fi.SetValue(Me, currentPage + 1)
Exit While
End If
firstRow = False
End While
If Me.PrintPages.Count > 0 AndAlso Not settings.PrintHierarchy Then
If currentY + Me.GetDataRowHeight(traverser.Current, rowLayout) < drawArea.Bottom OrElse _
skipPageCurrentY + Me.GetDataRowHeight(traverser.Current, rowLayout) < drawArea.Bottom Then
fi.SetValue(Me, currentPage + 1)
End If
Me.CurrentPrintPage += 1
Me.CurrentPrintPage = Me.CurrentPrintPage Mod Me.PrintPages.Count
If Me.CurrentPrintPage > 0 Then
If row Is Nothing Then
traverser.Reset()
Else
traverser.GoToRow(row)
End If
End If
End If
End Sub
End Class
WORKAROUND:
1. Create a custom GridTableElement and override the ProcessColumnEvent method.
2. Create a custom TableViewDefinition and override the CreateViewUIElement to return the custom table element.
3. Assign the custom view definition to the grid's ViewDefinition property
public class CustomGridTableElement : GridTableElement
{
protected override GridViewEventResult ProcessColumnEvent(GridViewColumn column, GridViewEvent eventData)
{
if (eventData.Info.Id == KnownEvents.PropertyChanged)
{
RadPropertyChangedEventArgs args = eventData.Arguments[0] as RadPropertyChangedEventArgs;
if (args.Property == GridViewColumn.IsVisibleProperty)
{
ViewElement.UpdateRowsWhenColumnsChanged();
if (this.GridViewElement.AutoSizeRows)
{
foreach (GridViewRowInfo row in this.ViewTemplate.Rows)
{
row.Height = -1;
}
this.UpdateLayout();
this.RowScroller.UpdateScrollRange();
}
return null;
}
}
return base.ProcessColumnEvent(column, eventData);
}
protected override Type ThemeEffectiveType
{
get { return typeof(GridTableElement); }
}
}
public class CustomTableViewDefinition : TableViewDefinition
{
public override IRowView CreateViewUIElement(GridViewInfo viewInfo)
{
return new CustomGridTableElement();
}
}
this.radGridView1.ViewDefinition = new CustomTableViewDefinition();