|
I renamed DataGridViewTextBoxCellEx to DataGridViewSpannedTextBoxCell in my code
|
|
|
|
|
|
Before the question, I'm number one fan of the DataGridView, so my congratulations for the work.
The column not expand.
I created the column as an example using the type DataGridViewTextBoxCellEx, however, does not appear in the combox ColumnSpan.
Dim RowDtGrid As New DataGridViewRow
RowDtGrid = DtGrid.Rows(0)
RowDtGrid.Cells("Coluna1").ColumnSpan = 3
What am I doing wrong?
In combox in Visual Studio, there is no ColumnSpan.
|
|
|
|
|
What combobox do you mean? Do sibling columns (other two) also support spanning (created from DataGridViewTextBoxCellEx or other )? Do you get some exception. Please, detail your problem.
|
|
|
|
|
Sorry, I was wrong to set variable.
Dim ColDtGrid As New SpannedDataGridView.DataGridViewTextBoxCellEx
ColDtGrid DtGrid.Rows(0).Cells("Column1")
ColDtGrid.ColumnSpan = 3
Now it worked fine.
|
|
|
|
|
That is because you have to cast it.
try this:
Dim RowDtGrid As New DataGridViewRow
RowDtGrid = DtGrid.Rows(0)
CType(RowDtGrid.Cells("Coluna1"), SpannedDataGridView.DataGridViewTextBoxCellEx).ColumnSpan = 3
|
|
|
|
|
Can DataGridViewButtonCell be used in the same DataGridView or must all cells implement ISpannedCell ?
|
|
|
|
|
Only cells that must be spanned or take part in spanning should implement the interface. Other may not.
|
|
|
|
|
Hi
A i've got problem with span behavior after binding to datgridview. I definied 2 columns of type DataGridVewTextBoxCell in datgidview and populate data by this source code (I have express edition 2010):
private void wypelnijGrid4()
{
Konfiguracja konf = new Konfiguracja();
string connStr = konf.GetConnectionString();
string sql = "select id,vakt from VERS";
OracleConnection conn = new OracleConnection();
conn.ConnectionString = connStr;
conn.Open();
sCommand = new OracleCommand(sql, conn);
sAdapter = new OracleDataAdapter(sCommand);
sBuilder = new OracleCommandBuilder(sAdapter);
sDs = new DataSet();
sAdapter.Fill(sDs, "vers");
sTable = sDs.Tables["vers"];
conn.Close();
dataGridView4.AutoGenerateColumns = false;
dataGridView4.DataSource = sDs.Tables["vers"];
var cell = (DataGridViewTextBoxCellEx)dataGridView4[0, 3];
cell.ColumnSpan = 2;
cell.RowSpan = 2;
}
Binding works and I see data in columns but span behaviuor doesn't work. Without databinding when I add rows manually (using datgridview.rows.add()) then code
var cell = (DataGridViewTextBoxCellEx)dataGridView4[0, 3];
cell.ColumnSpan = 2;
cell.RowSpan = 2;
works corectlly - any idea how can I solve the problem ?
|
|
|
|
|
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.
|
|
|
|
|