Link to home
Start Free TrialLog in
Avatar of DaFou
DaFou

asked on

DataGrid rowheight

Ola,

I have this datagrid with a datasource.
Every column displays fine but those who have a multiline value.

How do I make sure multiline values get displayed to their fullest automaticly?
Avatar of jatinderalagh
jatinderalagh
Flag of India image

Use this method for ur purpose.

public void AutoSizeGrid()
             {
                   // DataGrid should be bound to a DataTable for this part to
                   // work.
                   int numRows = ((DataTable)dataGrid1.DataSource).Rows.Count;
                   Graphics g = Graphics.FromHwnd(dataGrid1.Handle);
                   StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
                   SizeF size;
 
                   // Since DataGridRows[] is not exposed directly by the DataGrid
                   // we use reflection to hack internally to it.. There is actually
                   // a method get_DataGridRows that returns the collection of rows
                   // that is what we are doing here, and casting it to a System.Array
                   MethodInfo mi = dataGrid1.GetType().GetMethod("get_DataGridRows",
                         BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase | BindingFlags.Instance
                         | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
 
                  System.Array dgra = (System.Array)mi.Invoke(dataGrid1,null);
                   // Convert this to an ArrayList, little bit easier to deal with
                   // that way, plus we can strip out the newrow row.
                   ArrayList DataGridRows = new ArrayList();
                   foreach (object dgrr in dgra)
                   {
                         if (dgrr.ToString().EndsWith("DataGridRelationshipRow")==true)
                               DataGridRows.Add(dgrr);
                   }
                   // Now loop through all the rows in the grid
                   for (int i = 0; i < numRows; ++i)
                   {
                         // Here we are telling it that the column width is set to
                         // 400.. so size will contain the Height it needs to be.
                        // u need to set this column width according to ur size of column
                         size = g.MeasureString(dataGrid1[i,1].ToString(),dataGrid1.Font,400,sf);
                         int h = Convert.ToInt32(size.Height);
                         // Little extra cellpadding space
                         h = h + 8;
 
                        // Now we pick that row out of the DataGridRows[] Array
                         // that we have and set it's Height property to what we
                         // think it should be.
                         PropertyInfo pi = DataGridRows[i].GetType().GetProperty("Height");
                         pi.SetValue(DataGridRows[i],h,null);
 
                        // I have read here that after you set the Height in this manner that you should
                         // Call the DataGrid Invalidate() method, but I haven't seen any prob with not calling it..
 
                  }
                   g.Dispose();
             }
Jatinder
Avatar of DaFou
DaFou

ASKER

this wont compile, you are missing some namespaces?
using System.Reflection;
using System.Data;

And add this method to ur form.
replace datagrid1 with the name of ur datagrid
Avatar of DaFou

ASKER

You forgot the System.Collections aswell.

Also I am not happy with how it works coz when not altering this code my datagrid row that has a multiline value becomes really small.

And when making the value 8 bigger to something like 32 is works only for a 2 line value., But for 3 line values it does nto work.
THe whole idea is that is autogrows to fit the contents, howvever how many lines.

Also the need to be able to scroll in vertical direction is determined at the moment the row height is its original size.
So when i have 3 rows that would normaly ( without resiing ) not result in a vertical scrollbar, after applying the resize method the vertical scrollbar still is not available.

Now how do i fix those problems?
Change the code from

  size = g.MeasureString(dataGrid1[i,1].ToString(),dataGrid1.Font,400,sf);
                     int h = Convert.ToInt32(size.Height);
                     // Little extra cellpadding space
                     h = h + 8;

To

//Find here a number of lines in a row
// i am using two lines only
int numberOfLines = 2;
int h = (Convert.ToInt32(dataGrid1.Font.Height)+3) * numberOfLines;

and also you can comment   these lines
Graphics g = Graphics.FromHwnd(dataGrid1.Handle);
 g.Dispose();

Jatinder
Avatar of DaFou

ASKER

The whole idea was to have the datagrid autmaticly determine how high the row should be acording to how many lines are in one of its values.
So int numberOfLines = 2; will not work. Sometimes i have only 1 line sometimes maybe 4. and yet othertimes i have 3 lines. I dont know.
So If you dont know of a way to AUTOMATICLY do this then I am avraid your suggestion is of no use :-(
if u read the comment
//Find here a number of lines in a row

So i suppose you to do bit of work and find out number of lines in that particular row (DataGridRows[i])
and set the value of numberOfLines  accordingly.
And it does work if u see the working
 it loops through all the rows and adjust the rowheight of each row.
for example i have given u the code inwhich i fixed the row height for 2 lines.
Now it's upto you to find the nhumber of lines in that particular row and change the variable accordingly.

IF u still can't understand what it is doing change then add following lines of code after this line int numberOfLines = 2;

if(alternate)
{
      numberOfLines = 1;
 }
alternate = ! alternate;

and before this loop
   // Now loop through all the rows in the grid
                for (int i = 0; i < numRows; ++i)

Define bool alternate = false;

try this and u will get the first row for one line and second row for two lines and so on.

Avatar of DaFou

ASKER

How do i determine how many lines any of the columns of the current row have?
If you can show me that I am all sert, then i can add that to your previous code and everything is fine
search for "\r\n" in ur columns.
The number of lines = occurence of "\r\n" in ur columns
Avatar of DaFou

ASKER

HOw do i search the columns and count the \r\n ocurances?
ASKER CERTIFIED SOLUTION
Avatar of jatinderalagh
jatinderalagh
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is working code so load ur datagrid and then call AutoSizeGrid() method.
If your problem is not solved then  let me know.

Jatinder
Avatar of DaFou

ASKER

its almoste there. your code does neatly resize all the rows seperatly now.. excellent :-)
But the problem is is that when i have 2 multiline rows and they are greater then the datagrid container size a vertical scrolbar does not apear
becuase acording to the datagrid container the 2 rows do not exceed the height of the container but they once your method is done adjusting the heigt of the rows.
Shall i accept your answer with a B grade now or do you know how to prevent this problem aswell and receive an A grade?
Derive a DataGrid. In your derived grid, add a handler for the VertScrollBar.VisibleChanged event. In your handler, if the scrollbar is not visible, size it and position it, and then show it. The code below assumes no horizontal scrollbar is necessary. If it is present, you would have to adjust the sizing code the same way it's done in here for vertical scrollbar.


public class MyDataGrid : DataGrid
{
     public MyDataGrid()
     {
          //make scrollbar visible & hook up handler
          this.VertScrollBar.Visible = true;
          this.VertScrollBar.VisibleChanged += new EventHandler(ShowScrollBars);
     }
 
     private int CAPTIONHEIGHT = 21;
     private int BORDERWIDTH = 2;

     private void ShowScrollBars(object sender, EventArgs e)
     {
          if(!this.VertScrollBar.Visible)
          {
               int width = this.VertScrollBar.Width;
               this.VertScrollBar.Location = new Point(this.ClientRectangle.Width - width - BORDERWIDTH, CAPTIONHEIGHT);
               this.VertScrollBar.Size = new Size(width, this.ClientRectangle.Height - CAPTIONHEIGHT - BORDERWIDTH);
               this.VertScrollBar.Show();                    
          }
     }
 
}
 
Jatinder
Avatar of DaFou

ASKER

VertScrollBar is not an exsisting member :-(

or am i misunderstanding something?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial