|
Do columns 0 and 1 implement interface ISpannedCell (ex DataGridViewTextBoxCellEx)? All columns which must take part in spanning should realize the interface.
|
|
|
|
|
so good ,thank you for sharing the codes
|
|
|
|
|
hell0
i am directly binding to the datagridview.
but getting error
Unable to cast object of type 'System.Windows.Forms.DataGridViewTextBoxCell' to type 'SpannedDataGridView.DataGridViewTextBoxCellEx'.
|
|
|
|
|
Change type of column in Datgridview to DataGridVewTextBoxCell. If you don't use definition of column but you populate data in datgridview dynamicly just add column and bind it by DataPropertyName. You should solve your problem - anyway a i had the same problem but after solve it span stop work
|
|
|
|
|
Only cells that must be spanned or take part in spanning should implement the interface. Other may not. Auto generation replaces all columns to standard which do not support spanning.
So, if you want to span some cells you should manually construct grid (insert columns with span support where you need) and off auto generation.
|
|
|
|
|
I implemented this nice piece of code in VB, made some tweaks and fixed the issue with selecting a cell other than 0,0 within the span (outside of the posted source).
Even the C# projects could use the fix for span selection. This piece of code will allow you to select any cell within the span and have the span selected as if cell 0,0 within the span was selected. This code is used to force selection of a cell that is part of the spanned cell yet not the top left cell to always select the top left cell. It is a good hack that will make the span always look complete. In order to do this, you must know the requirement you used in the first place to determine the span and adapt for your needs. Hopefully the places you need to adapt make adaptations to should be clear. For C# you will need to convert the code from VB to C#:
Delegate Sub Grid_SetColumnIndex(ByVal i As Integer)
'============================================================================================
'*
'============================================================================================
Private Sub <<Name_of_your_Grid>>_EditingControlShowing(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles _
<<Name_of_your_Grid>>.EditingControlShowing
'If its a comment row and not cell 0 then force the event to be cell 0 completing the
' illusion of this hack ;-). Or meets the span requirements and isn't top left
' cell, adjust as needed.
If cParams.cGridVerification.GetIsRowComment(sender.CurrentRow.Index) And _
sender.CurrentCell.ColumnIndex <> 0 Then
'Cencel edit on the current cell
sender.BeginEdit(False)
'You cannot directly start the edit of another cell once you stoped the edit of a
' current cell, this gets around that issue.
Dim method As New GridOptions_SetColumnIndex(AddressOf GridOptions_BeginEditOfCell)
sender.BeginInvoke(method, 0)
End If
End Sub
'============================================================================================
'*
'============================================================================================
Private Sub Grid_BeginEditOfCell(ByVal columnIndex As Integer)
<<Name_of_your_Grid>>.CurrentCell = <<Name_of_your_Grid>>.CurrentRow.Cells(columnIndex)
<<Name_of_your_Grid>>.BeginEdit(True)
End Sub
As for the VB .NET version I submitted my source to the Alternatives tab within this article along with enhancements, painting fixes, the selection source, etc or...
DataGridVewTextBoxCell with Span Behaviour[^]
|
|
|
|
|
Done a great deal of looking online for this functionality. Can this be used in Visual Basic 2010? I am pretty new to the .net world and I am not sure how to implement this in vb
|
|
|
|
|
Thank you.
Yes, it can be used in VB. Just compile the sources (or take bin) and add the result assembly to references in your project.
|
|
|
|
|
when i compiled it to dll in c# and add reference in vb.net i gotta some errors
DirectCast(DataGridView1.Item(1, 3), SpannedDataGridView.DataGridViewTextBoxCellEx).ColumnSpan = 3
erorros :
Unable to cast object of type 'System.Windows.Forms.DataGridViewTextBoxCell' to type 'SpannedDataGridView.DataGridViewTextBoxCellEx'.
How can i fixed it ??
pls kindly convert it from c# to vb.net project and send to my email: nimol.elixir@gmail.com ,,
pls help me, i'm very need it..
|
|
|
|
|
Hello Sergey,
i really like this project!
I try to speed up my DataGridViews by enabling Double-Buffering, but sadly the DataGridViewTextBoxCellEx doesn't work with this - spanned cells don't paint correctly.
I got thus far: using DataGridView.CreateGraphics() in Paint(...) should't be used, but still something is missing...
Any idea?
|
|
|
|
|
Hello.
Whould you show your code, which doesn't work correctly?
|
|
|
|
|
well, essentially i used the sample code from the zip
in DemoForm.cs i added:
SetDoubleBuffered(dataGridView1);
to the constructor
code for SetDoubleBuffered():
public static void SetDoubleBuffered(Control control)
{
typeof(Control).InvokeMember("DoubleBuffered",
BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, control, new object[] { true }
);
}
(this has the same effect as deriving DataGridViewEx from DataGridView and setting this.Doublebuffered = true; in its contructor)
-> Effect: the spanned cells are incorrectly drawn, selection highlight is broken (use keyboard navigation for example)
i have a slightly adopted version of the sources, where i took some effort to overcome this, see
http://www.filedropper.com/spanneddatagridview[^]
(mainly changed some coding-style like braces)
best regards
|
|
|
|
|
Yes, you are right. DataGridView.CreateGraphics() in Paint() cause the problem. We should use buffer graphics, otherwise our painting will be corrupted, when buffer is applied. But using an instant graphics isn't a solution: we cant paint an expanded area.
I tried to use origin graphics and invalidate child cells in Paint(), this works, but hangs the app: Paint() is called very often. It's not good.
Now, I have not any good idea. I'm sorry.
|
|
|
|
|
Following code worked for me. But I don't know why. Smile | Replace your Paint method with this:
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
if (_ownerCell != null && _ownerCell.DataGridView == null)
{
_ownerCell = null;
}
if (DataGridView == null || (_ownerCell == null && _columnSpan == 1 && _rowSpan == 1))
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
return;
}
var ownerCell = this;
var columnIndex = ColumnIndex;
var columnSpan = _columnSpan;
var rowSpan = _rowSpan;
if (_ownerCell != null)
{
ownerCell = _ownerCell;
columnIndex = _ownerCell.ColumnIndex;
rowIndex = _ownerCell.RowIndex;
columnSpan = _ownerCell.ColumnSpan;
rowSpan = _ownerCell.RowSpan;
value = _ownerCell.GetValue(rowIndex);
errorText = _ownerCell.GetErrorText(rowIndex);
cellState = _ownerCell.State;
cellStyle = _ownerCell.GetInheritedStyle(null, rowIndex, true);
formattedValue = _ownerCell.GetFormattedValue(value, rowIndex, ref cellStyle, null, null, DataGridViewDataErrorContexts.Display);
}
if (CellsRegionContainsSelectedCell(columnIndex, rowIndex, columnSpan, rowSpan))
{
cellState |= DataGridViewElementStates.Selected;
}
RectangleF oldBounds = graphics.ClipBounds;
var cellBounds2 = DataGridViewCellExHelper.GetSpannedCellBoundsFromChildCellBounds(this, cellBounds, DataGridView.SingleVerticalBorderAdded(), DataGridView.SingleHorizontalBorderAdded());
clipBounds = DataGridViewCellExHelper.GetSpannedCellClipBounds(ownerCell, cellBounds2, DataGridView.SingleVerticalBorderAdded(), DataGridView.SingleHorizontalBorderAdded());
advancedBorderStyle = DataGridViewCellExHelper.AdjustCellBorderStyle(ownerCell);
using (var g = this.DataGridView.CreateGraphics())
{
g.SetClip(clipBounds);
ownerCell.NativePaint(g, clipBounds, cellBounds2, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts & ~DataGridViewPaintParts.Border);
if ((paintParts & DataGridViewPaintParts.Border) != DataGridViewPaintParts.None)
{
var leftTopCell = ownerCell;
var advancedBorderStyle2 = new DataGridViewAdvancedBorderStyle
{
Left = advancedBorderStyle.Left,
Top = advancedBorderStyle.Top,
Right = DataGridViewAdvancedCellBorderStyle.None,
Bottom = DataGridViewAdvancedCellBorderStyle.None
};
leftTopCell.PaintBorder(g, clipBounds, cellBounds2, cellStyle, advancedBorderStyle2);
var rightBottomCell = DataGridView[columnIndex + columnSpan - 1, rowIndex + rowSpan - 1] as DataGridViewSpannedTextBoxCell ?? this;
var advancedBorderStyle3 = new DataGridViewAdvancedBorderStyle
{
Left = DataGridViewAdvancedCellBorderStyle.None,
Top = DataGridViewAdvancedCellBorderStyle.None,
Right = advancedBorderStyle.Right,
Bottom = advancedBorderStyle.Bottom
};
rightBottomCell.PaintBorder(g, clipBounds, cellBounds2, cellStyle, advancedBorderStyle3);
}
}
graphics.SetClip(clipBounds);
ownerCell.NativePaint(graphics, clipBounds, cellBounds2, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts & ~DataGridViewPaintParts.Border);
if ((paintParts & DataGridViewPaintParts.Border) != DataGridViewPaintParts.None)
{
var leftTopCell = ownerCell;
var advancedBorderStyle2 = new DataGridViewAdvancedBorderStyle
{
Left = advancedBorderStyle.Left,
Top = advancedBorderStyle.Top,
Right = DataGridViewAdvancedCellBorderStyle.None,
Bottom = DataGridViewAdvancedCellBorderStyle.None
};
leftTopCell.PaintBorder(graphics, clipBounds, cellBounds2, cellStyle, advancedBorderStyle2);
var rightBottomCell = DataGridView[columnIndex + columnSpan - 1, rowIndex + rowSpan - 1] as DataGridViewSpannedTextBoxCell ?? this;
var advancedBorderStyle3 = new DataGridViewAdvancedBorderStyle
{
Left = DataGridViewAdvancedCellBorderStyle.None,
Top = DataGridViewAdvancedCellBorderStyle.None,
Right = advancedBorderStyle.Right,
Bottom = advancedBorderStyle.Bottom
};
rightBottomCell.PaintBorder(graphics, clipBounds, cellBounds2, cellStyle, advancedBorderStyle3);
}
graphics.SetClip(oldBounds);
}
|
|
|
|
|
I have some little-big problem with a spannedcolumn
Spanned over 4 cells, with
- datagridview autosizerowmode = allcells
- column.DefaultCellStyle.WrapMode = true
when the text (take a page of text for example) is inside the cell, it adds empty lines at the bottom for a certain amount.
if you don't use spaces it does not add the lines.
Any idea? or do you need more code?
|
|
|
|
|
Hi.
Yes, you're right, there is a problem. Here a code fixing the problem (not tested completely).
public class DataGridViewTextBoxCellEx: DataGridViewTextBoxCell, ISpannedCell
{
......
protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
{
var size = base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize);
if (OwnerCell != null) return size;
var grid = DataGridView;
var height = size.Height - Enumerable.Range(RowIndex + 1, RowSpan - 1)
.Select(index => grid.Rows[index].Height)
.Sum();
return new Size(size.Width, height);
}
......
}
Place the method into DataGridViewTextBoxCellEx class (or other).
Later I publish this changes.
|
|
|
|
|
I'm sorry for misunderstanding your question in the previous reply.
This problem is a problem/feature of DataGridViewTextBoxCell (you may test it) which I use, so I cant fix it in the near future.
I hope, I've answered to the question correctly now.
|
|
|
|
|
Question 1 :
When you use the CellPainting event of the datagridview... to change the cell color depending on a value, this occurs correctly EXCEPT for the spanned cells... any idea?
Question 2 :
How to bind the grid to a datasource so that every cell is of type datagridtextboxcolumnEX? after a standard bind , these are regular datacolumns....?
Kindly regards
Gert De Busser
Belgium .
example Question 1 :
Private Sub grdResult_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles grdResult.CellPainting
Try
If e.RowIndex >= 0 Then
If e.ColumnIndex = ResultaatKolom Then
If grdResult.Rows(e.RowIndex).Cells(ResultaatKolom).ReadOnly = False Then
e.CellStyle.BackColor = Color.Cornsilk
e.CellStyle.ForeColor = Color.Black
Else
e.CellStyle.BackColor = Color.White
e.CellStyle.ForeColor = Color.Black
End If
Else
e.CellStyle.BackColor = Color.White
e.CellStyle.ForeColor = Color.Black
End If
End If
Catch ex As Exception
MsgBox(ex.InnerException.ToString & ex.Message.ToString)
End Try
End Sub
Private Sub SetReadOnly()
Dim row As DataGridViewRow
For Each row In grdResult.Rows
Dim c As SpannedDataGridView.DataGridViewTextBoxCellEx
For Each c In row.Cells
If c.ColumnIndex = ResultaatKolom Then
If c.Value.ToString.Contains("0") Then
If AlleVeldenInvullen = True Then
c.ReadOnly = False
Else
c.ReadOnly = True
End If
DirectCast(c, SpannedDataGridView.DataGridViewTextBoxCellEx).ColumnSpan = 2
Else
c.ReadOnly = False
DirectCast(c, SpannedDataGridView.DataGridViewTextBoxCellEx).ColumnSpan = 1
End If
Else
c.ReadOnly = True
DirectCast(c, SpannedDataGridView.DataGridViewTextBoxCellEx).ColumnSpan = 1
End If
Next
grdResult.InvalidateRow(row.Index)
Next
grdResult.Refresh()
End Sub
|
|
|
|
|
Hi.
A for Q1: Use DataGridVeiw.CellFormatting event to set colors.
A for Q2: Set DataGridVeiw.AutoGenerateColumns = false before applying data source.
|
|
|
|
|
works perfect. Thx! cellformatting <> cellpainting ... sometimes strange.
|
|
|
|
|
It's practice from documentation.
|
|
|
|
|
Hi, first of all great work. I was checking your demo and when I set the first row to frozen it began to draw the cell overlaped, it seems that it looses the correct position of the cells.
Regards
|
|
|
|
|
Hi. Thank you very much!
Yes, you are right, it take place. But do you propose to froze whole spanned row when a part is frozen?
|
|
|
|
|
As a matter of fact yes, I believe that's probably one reason of the bug, however I believe it has something to do in the way the boundaries are calculated.
Well it is not a must to have frozen cells in my application, and definitely having merging cells is need it. Eather way I will try to see how this can be fix and if I had the solution I will post it here.
Thanks
|
|
|
|
|
It would be wonderful.
Thanks.
|
|
|
|
|