DataGrid Row Height and Vertical Scrollbar

M

Mike Livenspargar

I'm using the method described in George Shepard's Windows Forms FAQ to
programatically alter row heights in a DataGrid:

http://www.syncfusion.com/FAQ/WinForms/FAQ_c44c.asp#q1076q

The row heights are altered correctly but the vertical scrollbar on the
DataGrid seems to be unaware of the change in row heights. If you run the
sample code shown below you will find you are unable to scroll to the end of
the data in the grid. If, however, you scroll down as far as you can and
minimize then restore the form, the scrollbar adjusts correctly and you can
scroll to the end of the data. If you leave the scrollbar at the top of the
data and minimize and restore, the scrollbar does not adjust and you are
still unable to scroll to the end.

I have tried various combinations of Invalidate() and PerformLayout() to no
avail. How can I get the vertical scrollbar to adjust to the true height of
the datagrid rows without asking the user to scroll to the end of the data,
minimize the form and then restore it?

Thanks,
Mike

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace DataGridTest
{
public class Form1 : System.Windows.Forms.Form
{
private ArrayList _dataList;

private System.Windows.Forms.DataGrid dataGrid1;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}

private void InitGrid()
{
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "ArrayList";
DataGridTextBoxColumn col = new DataGridTextBoxColumn();
col.HeaderText = "Text";
col.MappingName = "Text";
col.Width = 50;
tableStyle.GridColumnStyles.Add(col);
dataGrid1.TableStyles.Add(tableStyle);
dataGrid1.SetDataBinding(_dataList, null);
}

private void FiddleWithTheHeights()
{
MethodInfo mi =
dataGrid1.GetType().GetMethod("get_DataGridRows",BindingFlags.FlattenHierarc
hy | BindingFlags.IgnoreCase | BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

System.Array dgra = (System.Array)mi.Invoke(dataGrid1, null);

ArrayList rowObjects = new ArrayList();
foreach (object dgrr in dgra)
{
if
(dgrr.ToString().EndsWith("DataGridRelationshipRow")==true)
rowObjects.Add(dgrr);
}

using(Graphics g = dataGrid1.CreateGraphics())
{
StringFormat sf = new
StringFormat(StringFormat.GenericTypographic);
for(int index = 0; index < _dataList.Count; index++)
{
SizeF size = g.MeasureString(dataGrid1[index,
0].ToString(), dataGrid1.Font, 50, sf);
int height = Convert.ToInt32(size.Height);
height += 8;
PropertyInfo pi =
rowObjects[index].GetType().GetProperty("Height");
pi.SetValue(rowObjects[index], height, null);
}
}

dataGrid1.PerformLayout();
dataGrid1.Invalidate();
}

private void InitData()
{
_dataList = new ArrayList();
_dataList.Add(new GridData("one"));
_dataList.Add(new GridData("one\ntwo"));
_dataList.Add(new GridData("one\ntwo\nthree"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour\nfive"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour\nfive\nsix"));
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGrid1 = new System.Windows.Forms.DataGrid();

((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
this.SuspendLayout();
//
// dataGrid1
//
this.dataGrid1.DataMember = "";
this.dataGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGrid1.HeaderForeColor =
System.Drawing.SystemColors.ControlText;
this.dataGrid1.Location = new System.Drawing.Point(0, 0);
this.dataGrid1.Name = "dataGrid1";
this.dataGrid1.Size = new System.Drawing.Size(224, 173);
this.dataGrid1.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(224, 173);
this.Controls.Add(this.dataGrid1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{
InitData();
InitGrid();
FiddleWithTheHeights();
}
}

public class GridData
{
private string _text;

public GridData(string text)
{
_text = text;
}

public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
}
}
 
C

ClayB [Syncfusion]

After setting the new rowheights, I think you will have to set the
VScrollBar.Maximum. You can get at the scrollbar with this code. (Not sure
about why adding 2 works but it seemed to handle things with your code, even
if I added a few more rows.????)

//your code to change heights

VScrollBar vSB = null;

foreach(Control c in this.dataGrid1.Controls)
{
if(c is VScrollBar)
{
vSB = c as VScrollBar;
}
}
vSB.Maximum += 2;

dataGrid1.PerformLayout();
dataGrid1.Invalidate();
}


===========================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools



Mike Livenspargar said:
I'm using the method described in George Shepard's Windows Forms FAQ to
programatically alter row heights in a DataGrid:

http://www.syncfusion.com/FAQ/WinForms/FAQ_c44c.asp#q1076q

The row heights are altered correctly but the vertical scrollbar on the
DataGrid seems to be unaware of the change in row heights. If you run the
sample code shown below you will find you are unable to scroll to the end of
the data in the grid. If, however, you scroll down as far as you can and
minimize then restore the form, the scrollbar adjusts correctly and you can
scroll to the end of the data. If you leave the scrollbar at the top of the
data and minimize and restore, the scrollbar does not adjust and you are
still unable to scroll to the end.

I have tried various combinations of Invalidate() and PerformLayout() to no
avail. How can I get the vertical scrollbar to adjust to the true height of
the datagrid rows without asking the user to scroll to the end of the data,
minimize the form and then restore it?

Thanks,
Mike

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace DataGridTest
{
public class Form1 : System.Windows.Forms.Form
{
private ArrayList _dataList;

private System.Windows.Forms.DataGrid dataGrid1;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}

private void InitGrid()
{
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "ArrayList";
DataGridTextBoxColumn col = new DataGridTextBoxColumn();
col.HeaderText = "Text";
col.MappingName = "Text";
col.Width = 50;
tableStyle.GridColumnStyles.Add(col);
dataGrid1.TableStyles.Add(tableStyle);
dataGrid1.SetDataBinding(_dataList, null);
}

private void FiddleWithTheHeights()
{
MethodInfo mi =
dataGrid1.GetType().GetMethod("get_DataGridRows",BindingFlags.FlattenHierarc
hy | BindingFlags.IgnoreCase | BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

System.Array dgra = (System.Array)mi.Invoke(dataGrid1, null);

ArrayList rowObjects = new ArrayList();
foreach (object dgrr in dgra)
{
if
(dgrr.ToString().EndsWith("DataGridRelationshipRow")==true)
rowObjects.Add(dgrr);
}

using(Graphics g = dataGrid1.CreateGraphics())
{
StringFormat sf = new
StringFormat(StringFormat.GenericTypographic);
for(int index = 0; index < _dataList.Count; index++)
{
SizeF size = g.MeasureString(dataGrid1[index,
0].ToString(), dataGrid1.Font, 50, sf);
int height = Convert.ToInt32(size.Height);
height += 8;
PropertyInfo pi =
rowObjects[index].GetType().GetProperty("Height");
pi.SetValue(rowObjects[index], height, null);
}
}

dataGrid1.PerformLayout();
dataGrid1.Invalidate();
}

private void InitData()
{
_dataList = new ArrayList();
_dataList.Add(new GridData("one"));
_dataList.Add(new GridData("one\ntwo"));
_dataList.Add(new GridData("one\ntwo\nthree"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour\nfive"));
_dataList.Add(new GridData("one\ntwo\nthree\nfour\nfive\nsix"));
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGrid1 = new System.Windows.Forms.DataGrid();

((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
this.SuspendLayout();
//
// dataGrid1
//
this.dataGrid1.DataMember = "";
this.dataGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGrid1.HeaderForeColor =
System.Drawing.SystemColors.ControlText;
this.dataGrid1.Location = new System.Drawing.Point(0, 0);
this.dataGrid1.Name = "dataGrid1";
this.dataGrid1.Size = new System.Drawing.Size(224, 173);
this.dataGrid1.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(224, 173);
this.Controls.Add(this.dataGrid1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{
InitData();
InitGrid();
FiddleWithTheHeights();
}
}

public class GridData
{
private string _text;

public GridData(string text)
{
_text = text;
}

public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
}
}
 
M

Mike Livenspargar

Thank you, adding 2 to the vertical scrollbar Maximum does indeed allow the
given sample to work. Unfortunately this method doesn't seem to apply
generally. For instance, I added more data to be shown in the grid
(following the pattern in the sample I went up to thirteen) and discovered
that the vertical scrollbar once again failed to allow scrolling to the end
of the data. I tried increasing the amount added to the vertical scrollbar
Maximum to no avail. Worse, it doesn't work at all in the real-world
situation I was trying to emulate with the sample. It turns out that even
the minimize/restore trick I described in the original post doesn't work
when there is more than one page worth of data below the point to which you
can scroll with the vertical bar.

At this point I think I'll wait for the DataGridView which, in my quick read
of its projected abilities, looks as if it has row height adjustments
legitimately available. I'll simulate a read-only grid with a scrollable
panel and labels while waiting.

Thanks again,
Mike
 
Y

Ying-Shen Yu[MSFT]

Hi Mike,

I found another article about auto size the datagrid on CodeProject , you
try it to see if it resolves this issue:
<Advanced DataGrid sizing>
http://www.codeproject.com/cs/miscctrl/WCsAutoSizeDataGrid.asp

Thanks!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
M

Mike Livenspargar

Thanks, but that doesn't work either. Combining the AutoSizeDataGrid code
and the data I provided in my original sample (now counting to thirteen) I
discovered the following: if I ran the code to display an empty grid and
then clicked the Add button, I was able to scroll to the end of the data
with no problem. If, however, I prepopulate the grid's datasource with my
data then when the grid displays I cannot scroll to the end of the data with
the vertical scrollbar.

Given this behavior I suspected ListChanged events were being raised by the
data source, causing the grid to calculate it's vertical scrollbar values
correctly. I've tried having my datasource raise a ListChanged.ItemAdded
event to no avail (the event is being raised but the vertical scrollbar
values remain incorrect).

I'm still thinking I'll just simulate a DataGrid with a scrollable panel and
labels, pending the DataGridView control.

Thanks,
Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top