Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

DataGrid rowheight

Posted on 2005-01-03
16
Medium Priority
?
140 Views
Last Modified: 2012-06-08
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?
0
Comment
Question by:DaFou
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 7
16 Comments
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12950256
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
0
 
LVL 2

Author Comment

by:DaFou
ID: 12950991
this wont compile, you are missing some namespaces?
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12951005
using System.Reflection;
using System.Data;

And add this method to ur form.
replace datagrid1 with the name of ur datagrid
0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
LVL 2

Author Comment

by:DaFou
ID: 12951278
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?
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12951637
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
0
 
LVL 2

Author Comment

by:DaFou
ID: 12952074
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 :-(
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12959321
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.

0
 
LVL 2

Author Comment

by:DaFou
ID: 12960057
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
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12960365
search for "\r\n" in ur columns.
The number of lines = occurence of "\r\n" in ur columns
0
 
LVL 2

Author Comment

by:DaFou
ID: 12960702
HOw do i search the columns and count the \r\n ocurances?
0
 
LVL 11

Accepted Solution

by:
jatinderalagh earned 2000 total points
ID: 12961323
Here is the code u need i modified it

      public void AutoSizeGrid()
             {
                   // DataGrid should be bound to a DataTable for this part to
                   // work.
                   int numRows = ((DataTable)dataGrid1.DataSource).Rows.Count;
                  int numCols = ((DataTable)dataGrid1.DataSource).Columns.Count;
                   //Graphics g = Graphics.FromHwnd(dataGrid1.Handle);
                   StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
                    
                   // 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
                         //Find here a number of lines in a row
                        int numberOfLines = 1;
                        for( int j=0; j<numCols; j++)
                        {
                              //loop through all the columns aand find the maximum number of lines
                              string[] items =      dataGrid1[i,j].ToString().Split('\n');
                              if(items.Length > numberOfLines)
                              {
                                    numberOfLines = items.Length;
                              }
                        }
                  
                        int h = (Convert.ToInt32(dataGrid1.Font.Height)+3) * numberOfLines;
                           
                        // 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);

                        //call the invalidate for repainting it.
                        dataGrid1.Invalidate();
                   }
                   
             }

But it looks like u havn't read the code.

Jatinder
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 12969095
This is working code so load ur datagrid and then call AutoSizeGrid() method.
If your problem is not solved then  let me know.

Jatinder
0
 
LVL 2

Author Comment

by:DaFou
ID: 13002369
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?
0
 
LVL 11

Expert Comment

by:jatinderalagh
ID: 13010321
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
0
 
LVL 2

Author Comment

by:DaFou
ID: 13011744
VertScrollBar is not an exsisting member :-(

or am i misunderstanding something?
0
 
LVL 11

Assisted Solution

by:jatinderalagh
jatinderalagh earned 2000 total points
ID: 13013035
VertScrollBar is not a public variable.

you need to inherit the class from  DataGrid
and with in this custom class say MyDataGrid you need to access it.

And on your form you need to use MyDataGrid rather then DataGrid class.

It will be your custom control

Just add a new class to your project. Delete all the code in it and copy paste the below written code.

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

namespace TestApp
{
      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();                    
                  }
            }
 
      }

}


Now in your form where you are using private System.Windows.Forms.DataGrid dataGrid1;
just change this to TestApp.MyDataGrid dataGrid1;
And in InitializeComponent() method
change this line this.dataGrid1 = new System.Windows.Forms.DataGrid();
to this.dataGrid1 = new TestApp.MyDataGrid();

Jatinder
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question