I have a gridview control with more than 50 item, how can I display them in the gridview with there full width.
I have tried AutoResizeMode, but it shrink all of them in the viewable area of the grid, I need that all columns
get resized to it's contents regardless of it's visuallity.
Is this possible...
Best regards
45 Answers, 1 is accepted
Thank you for contacting us. I am not sure that I understand your question correctly. However, you can control the column width by using AutoSizeColumnsMode property. When it is set to Fill all columns are resized to fit to the available grid area. When it is set to None, its width is controlled by GridViewColumn.Width property. You can call MasterGridViewTemplate.BestFitColumns method to let RadGridView calculate the optimal width. I hope this helps, if you have further questions, please write me back.
Regards,
Jack
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
I am not sure that I understand the issue correctly. From what you described, I think that the best option is to call BestFitColumns method. Please send me your application, this will allow me to research the issue further. I am looking forward to your reply.
Regards,
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
What I need is to be able to set one column to Fill and all others fixed width.
How do I do that ?
You can achieve this by setting MinWidth and MaxWidth properties for all columns that should have fixed size and by using fill mode. Consider the sample below:
for
(
int
i = 0; i <
this
.radGridView1.Columns.Count - 1; i++)
{
this
.radGridView1.MasterGridViewTemplate.Columns[i].MinWidth = 60;
this
.radGridView1.MasterGridViewTemplate.Columns[i].MaxWidth = 60;
this
.radGridView1.MasterGridViewTemplate.Columns[i].Width = 60;
}
this
.radGridView1.MasterGridViewTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
Best wishes,
Jack
the Telerik team
I want to be able to say something like :
dataGridView.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView.Columns[3].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
thus making the first 3 columns fit to the size of the largest text, and the forth to fill the rest of the grid.
Is this possible with the RadGridView?
Thanks.
This feature is not available in RadGridView. However, we plan to extend our column sizing modes and I will add this as a feature request. It will be considered when planning our future versions and if more people request the same feature, we will raise its priority.
Should you have any other questions, don't hesitate to ask.
Jack
the Telerik team
I have financial data and a "description" column. I want to ensure that the full contents of the financial data are shown and grow/shrink the "description" column so needed. If the user resizes the form, the financial data columns should stay the same size (fit to contents) and the "description" column show grow or shrink.
So there is no work around for this at this point in time?
Sadly there is a strange thing in the radGridView1.Columns[0].BestFit(); in my tests if you have a pyramidal structure for the data contained in the column, let's say in column 0 we have 10 rows and there is a letter on the first, row, 2 on the second, and so on, if you change the size of the column to cover most of the text in the column and create a button that calls just BestFit() on the column you will see that it takes more than a few presses until all the content is visible...
Deborah, if you just have one column that you always need at maximum width, on data binding complete, you could just go trough all of the rows, get the maximum string size for that column and based on that calculate the min, max & width of that column and just like Jack said, set the grid
this
.radGridView1.MasterGridViewTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
This is not a clean solution, but it passes as a workaround until a fix will be released...
void
radGridView1_DataBindingComplete(
object
sender, Telerik.WinControls.UI.GridViewBindingCompleteEventArgs e)
{
var maxString =
string
.Empty;
foreach
(var row
in
radGridView1.Rows)
{
var value = row.Cells[0].Value.ToString();
maxString = maxString.Length > value.Length ? maxString : value;
}
var minWidth = radGridView1.CreateGraphics().MeasureString(maxString, radGridView1.Font);
radGridView1.Columns[0].MinWidth = (
int
)minWidth.Width + 5;
radGridView1.Columns[0].MaxWidth = (
int
)minWidth.Width + 5;
radGridView1.Columns[0].Width = (
int
)minWidth.Width + 5;
}
Hope this helps, and hope that the problem with BestFit() on the column will be fixed soon.
Best Regards,
Emanuel Varga
that problem was troubling me as well and i would like to join the feature request fraction to raise the priority of the task.
Thank you and have a nice weekend!
Bernd
When the page first comes up, the columns correctly fill the grid. However, when I rebind the second grid, the spacing is no longer correct. It looks like it may be providing space for a scroll bar? (But my grid is a standard # of rows and columns, so there should never need to be a scroll bar.)
Bottom line, it leaves a white column of empty space between the last column of data and the edge of the grid which is not acceptable to my customer for their product. Again, this only happens AFTER a rebind. It works fine when it is first displayed on the screen.
The only way around this I found was to clear the grid columns and rebuild them (instead of just rebinding the data in the columns.)
So if you could look into this one as well I would appreciate it.
Thanks!
Thank you for this explanation. I understand what you want to achieve. You should use the AutoSizeColumnsMode set to Fill. Before setting this property set the desired column size for the financial column and set its AllowResize property to false. This will fix it size and it will not change when RadGridView grows/shrinks. Here is a sample:
this
.radGridView1.Columns[
"Value"
].Width = 120;
this
.radGridView1.Columns[
"Value"
].AllowResize =
false
;
this
.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
I hope this helps. If you have any further questions, do not hesitate to ask.
Best wishes, Jack
the Telerik team
We are getting closer, but that won't quite work for me. The user can change the font for the application (just like the little font size area in IE). So if the font changes, the grid columns do need to resize. With my original settings, this was working fine (until I rebound the grid). With these new settings, that no longer works.
My current work around is just to delete all of the columns and rebuild the grid, which works, but can't be all that efficient.
Thanks again!
Did you read my reply from earlier?, there, on data binding complete, you will calculate the maximum size of the column based on it's content using the Font on the grid, when the user changes the font, the font on the grid will change also, so this will continue to work, try it and please let me know....
Just put that in a method and call it also when the user changes the font, register for the FontChanged event and call it from there, it should do what you need
Best Regards,
Emanuel Varga
When I added code to hard-code the column width, it is even more apparent that it is attempting to save that space. I attached a screen shot.
I've tried to reproduce your issue, by using the same 2 grids one for data, and one for details that loads when CurrentRowChanged in the main grid.
I will attach here the test I've made, please let me know what is different in your scenario.
namespace
TestGridSourceDetails
{
using
System;
using
System.ComponentModel;
using
System.Text;
using
System.Windows.Forms;
using
Telerik.WinControls.UI;
public
partial
class
Form1 : Form
{
private
RadGridView radGridViewMain;
private
RadGridView radGridViewChild;
public
Form1()
{
InitializeComponent();
this
.Size =
new
System.Drawing.Size(800, 600);
this
.Load +=
new
EventHandler(Form1_Load);
}
void
Form1_Load(
object
sender, EventArgs e)
{
radGridViewMain =
new
RadGridView();
radGridViewMain.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
radGridViewMain.CurrentRowChanged +=
new
CurrentRowChangedEventHandler(radGridViewMain_CurrentRowChanged);
radGridViewMain.DataSource =
new
TestsCollection(10);
radGridViewMain.Dock = DockStyle.Left;
radGridViewMain.Size =
new
System.Drawing.Size(
this
.Width / 2 - 10,
this
.Height);
radGridViewChild =
new
RadGridView();
radGridViewChild.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
radGridViewChild.Dock = DockStyle.Right;
radGridViewChild.Size =
new
System.Drawing.Size(
this
.Width / 2 - 10,
this
.Height);
this
.Controls.Add(radGridViewMain);
this
.Controls.Add(radGridViewChild);
}
void
radGridViewMain_CurrentRowChanged(
object
sender, CurrentRowChangedEventArgs e)
{
var currentItem = (Test)radGridViewMain.CurrentRow.DataBoundItem;
radGridViewChild.DataSource =
new
TestDataCollection(currentItem.Id, 10);
}
}
#region Helpers
public
class
Test
{
public
Test(
int
id,
string
name)
{
this
.Id = id;
this
.Name = name;
}
public
int
Id
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
}
public
class
TestData
{
public
TestData(
int
id,
int
testId,
string
name)
{
this
.Id = id;
this
.TestId = testId;
this
.Name = name;
}
public
int
Id
{
get
;
set
;
}
public
int
TestId
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
}
public
class
TestsCollection : BindingList<Test>
{
public
TestsCollection(
int
noItems)
{
for
(
int
i = 0; i < noItems; i++)
{
this
.Add(
new
Test(i, RandomString.GetRandomString(DateTime.Now.Millisecond,
new
Random(7).Next(10, 20))));
}
}
}
public
class
TestDataCollection : BindingList<TestData>
{
public
TestDataCollection(
int
testId,
int
noItems)
{
for
(
int
i = 0; i < noItems; i++)
{
this
.Add(
new
TestData(i, testId, RandomString.GetRandomString(DateTime.Now.Millisecond,
new
Random(7).Next(10, 20))));
}
}
}
internal
static
class
RandomString
{
public
static
string
GetRandomString(
int
initialSeed,
int
size)
{
StringBuilder builder =
new
StringBuilder();
Random random =
new
Random(initialSeed);
char
ch;
for
(
int
i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return
builder.ToString();
}
}
#endregion Helpers
}
Best Regards,
Emanuel Varga
Sincerely yours,
Jack
the Telerik team
If I take BestFitColumns out, it appears to be stopping this behavior.
I decided to try to implement this code that you provided using MeasureString. It does not work in the following cases:
- The cell is wrapped (it attempts to fit the entire contents instead of allowing the wrap to occur)
- The cell is formatted (it ignores the formatting, causing the size to be inaccurate)
- The cell's header is longer than its text.
- The cell's header length is not longer, but its measure size is (example: phone numbers since numbers are often narrower than letters in the header)
- The cell is bound to a combobox (it uses the Value and not the DisplayValue).
- I tried using the .Text property, but it does not appear to support that like the ASP.Net version seems to have.
I have found work arounds for the first four, but am really stuck on the last one. Here is my code:
Private
Sub
SCStarDataGrid_DataBindingComplete(
ByVal
sender
As
Object
,
ByVal
e
As
Telerik.WinControls.UI.GridViewBindingCompleteEventArgs)
Handles
Me
.DataBindingComplete
If
Me
.Rows.Count > 0
Then
Dim
largestString
As
String
For
Each
col
In
Me
.Columns
' For any wrap columns, set a default minimum width
If
col.WrapText =
True
Then
col.MinWidth = 20
col.Width = 20
Else
' Start with the header text
largestString = col.HeaderText
For
Each
row
In
Me
.Rows
Dim
cellValue =
If
(row.Cells(col.Index).Value
Is
Nothing
,
String
.Empty, row.Cells(col.Index).Value.ToString)
' Format the cell value based on the provided format string
If
Not
String
.IsNullOrWhiteSpace(col.FormatString)
Then
' The date formatting only works if the data type is a date, so try to convert it.
Dim
cellDate
As
DateTime
If
DateTime.TryParse(cellValue, cellDate)
Then
cellValue =
String
.Format(col.FormatString, cellDate)
Else
cellValue =
String
.Format(col.FormatString, cellValue)
End
If
End
If
largestString =
If
(largestString.Length >= cellValue.Length, largestString, cellValue)
Next
Dim
columnSize =
Me
.CreateGraphics().MeasureString(largestString,
Me
.Font)
Dim
columnHeaderSize =
Me
.CreateGraphics.MeasureString(col.HeaderText,
Me
.Font)
Dim
columnWidth =
If
(columnSize.Width > columnHeaderSize.Width, columnSize.Width, columnHeaderSize.Width)
col.MinWidth =
CType
(columnWidth,
Integer
) + 5
col.Width =
CType
(columnWidth,
Integer
) + 5
End
If
Next
End
If
End
Sub
Any help would be appreciated.
I have a solution for you, but it's not a clean one, but it will work in all possible cases, and you don't have to use that complicated calculation function, but I'm not sure if it's the cleanest way to do things, but it will work.
From the previous posts, i know you are creating a custom grid control, and this is good because this solution also requires you to hold a dictionary of strings.
The actual .Text property of a cell is just available in the CellFormatting event and in the RowFormatting event,
Please take a look at the following example:
C#
Dictionary<
string
,
string
> dictionary =
new
Dictionary<
string
,
string
>();
void
radGridView1_CellFormatting(
object
sender, CellFormattingEventArgs e)
{
var column = e.CellElement.ColumnInfo;
var text = e.CellElement.Text;
if
(
string
.IsNullOrEmpty(text))
{
return
;
}
if
(dictionary[column.HeaderText].Length < text.Length)
{
dictionary[column.HeaderText] = text;
column.MinWidth = (
int
)(
this
.CreateGraphics().MeasureString(text,
this
.Font).Width+8);
}
}
and VB:
Private
dictionary
As
New
Dictionary(Of
String
,
String
)()
Private
Sub
radGridView1_CellFormatting(sender
As
Object
, e
As
CellFormattingEventArgs)
Dim
column = e.CellElement.ColumnInfo
Dim
text = e.CellElement.Text
If
String
.IsNullOrEmpty(text)
Then
Return
End
If
If
dictionary(column.HeaderText).Length < text.Length
Then
dictionary(column.HeaderText) = text
column.MinWidth =
CInt
(
Me
.CreateGraphics().MeasureString(text,
Me
.Font).Width + 8)
End
If
End
Sub
The idea here is to hold a dictionary with the column header text as the key and the largest string on that column as the value, and setting the minimum width on the column based on that value.
Please let me know what you think about this.
Best Regards,
Emanuel Varga
again, C#
Dictionary<
string
,
string
> dictionary =
new
Dictionary<
string
,
string
>();
void
radGridView1_CellFormatting(
object
sender, CellFormattingEventArgs e)
{
var column = e.CellElement.ColumnInfo;
var text = e.CellElement.Text;
if
(
string
.IsNullOrEmpty(text))
{
return
;
}
if
(dictionary[column.HeaderText].Length < text.Length)
{
dictionary[column.HeaderText] = text;
column.MaxWidth = (
int
)(
this
.CreateGraphics().MeasureString(text,
this
.Font).Width + 8);
column.Width = column.MaxWidth;
column.MinWidth = column.MaxWidth;
}
}
void
radGridView1_DataBindingComplete(
object
sender, GridViewBindingCompleteEventArgs e)
{
var grid = sender
as
RadGridView;
foreach
(var column
in
grid.Columns)
{
dictionary.Add(column.HeaderText, column.HeaderText);
column.MaxWidth = (
int
)(
this
.CreateGraphics().MeasureString(column.HeaderText,
this
.Font).Width + 8);
column.Width = column.MaxWidth;
column.MinWidth = column.MaxWidth;
}
}
and VB:
Private
dictionary
As
New
Dictionary(Of
String
,
String
)()
Private
Sub
radGridView1_CellFormatting(sender
As
Object
, e
As
CellFormattingEventArgs)
Dim
column = e.CellElement.ColumnInfo
Dim
text = e.CellElement.Text
If
String
.IsNullOrEmpty(text)
Then
Return
End
If
If
dictionary(column.HeaderText).Length < text.Length
Then
dictionary(column.HeaderText) = text
column.MaxWidth =
CInt
(
Me
.CreateGraphics().MeasureString(text,
Me
.Font).Width + 8)
column.Width = column.MaxWidth
column.MinWidth = column.MaxWidth
End
If
End
Sub
Private
Sub
radGridView1_DataBindingComplete(sender
As
Object
, e
As
GridViewBindingCompleteEventArgs)
Dim
grid = TryCast(sender, RadGridView)
For
Each
column
As
var
In
grid.Columns
dictionary.Add(column.HeaderText, column.HeaderText)
column.MaxWidth =
CInt
(
Me
.CreateGraphics().MeasureString(column.HeaderText,
Me
.Font).Width + 8)
column.Width = column.MaxWidth
column.MinWidth = column.MaxWidth
Next
End
Sub
Again, please let me know if this is ok for you,
Best Regards,
Emanuel Varga
@Deborah i was wondering if the solution i offered helped you solve your issues?
Best Regards,
Emanuel Varga
I am in California ... so I just got to work a few minutes ago. I will try this later this morning.
My biggest concern in just looking at the code is performance. The Formatting event is generated 100's of times.
Longer term, will you be adding a .Text or .FormattedValue property so we can access the shown value of the column outside of the Formating event?
Thanks again!
I know that the CellFormatting event is fired all the time, a maybe slightly faster option would be the RowFormatting event, but i am just trying to offer some workarounds that will do what you require at least until this issue will be fixed.
Please let me know if this works as expected.
Best Regards,
Emanuel Varga
It seems that setting the .Width property in the DataBindingComplete causes the CellFormatting event to occur in some cases.
This is what is happening:
1) DataBindingComplete resizes the first column based on the column header size.
2) This causes the CellFormatting event on the second column, so the code generates an exception because it is trying to update the text in a Dictionary entry that has not yet been defined ("The given Key was not present in the dictionary.")
So, I assume I have several options here:
1) Modify the code in the CellFormatting to add the dictionary entry if it does not exists yet. I would also have to change the code then in DataBindingComplete to do the same thing so I don't overwrite the value set up in the CellFormatting event.
2) I need to initialize the dictionary without setting the column widths yet and instead set the column widths in the CellFormatting event.
3) ??? Other options?
I do have one other problem, however. If the user enters a large amount of text, one column can overwhelm the grid, forcing the other columns to become too small or off the screen. The client does not want the column to wrap or to scroll, but instead to show an ellipsis if the column text is too long.
So I assume I also need to add to this some calculation to ensure that the total widths of all columns does not exceed the amount of space given to the grid on the form. Any tips or links on this calculation?
And at least like that you can provide an interface for the user to customize the grid based on his/her needs, and use a Save / Load layout to load the settings for the grid, usually more customizations => happier customers.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
Any code examples to kickstart this? (I have two weeks to finish the application and can't afford to spend 1 week of it getting the grids to work correctly. So any tips for how to write all of this code quickly would be appreciated.)
Or how do I determine the maximum width I can fill with the columns?
Thanks!
Is there an event I can use at that point to readjust the column widths if the total width is then too large?
Here the max width for the ID column is 10% and for the Date is 20%
C#:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Windows.Forms;
using
Telerik.WinControls.UI;
public
partial
class
Form1 : Form
{
private
RadGridView radGridView1;
private
TestsCollection collection =
new
TestsCollection(1000);
public
Form1()
{
InitializeComponent();
this
.Controls.Add(radGridView1 =
new
RadGridView());
radGridView1.Dock = DockStyle.Fill;
radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
}
protected
override
void
OnLoad(EventArgs e)
{
base
.OnLoad(e);
radGridView1.AddNewRowPosition = SystemRowPosition.Top;
radGridView1.DataBindingComplete +=
new
GridViewBindingCompleteEventHandler(radGridView1_DataBindingComplete);
radGridView1.CellFormatting +=
new
CellFormattingEventHandler(radGridView1_CellFormatting);
SetColumnPercentage(
"Id"
, 10);
SetColumnPercentage(
"Date"
, 20);
radGridView1.DataSource = collection;
}
protected
override
void
OnSizeChanged(EventArgs e)
{
base
.OnSizeChanged(e);
radGridView1.Refresh();
}
Dictionary<
string
,
string
> dictionary =
new
Dictionary<
string
,
string
>();
Dictionary<
string
,
int
> maxColumnWidthPercentage =
new
Dictionary<
string
,
int
>();
public
void
SetColumnPercentage(
string
headerText,
int
percentage)
{
if
(maxColumnWidthPercentage.ContainsKey(headerText))
{
maxColumnWidthPercentage[headerText] = percentage;
return
;
}
maxColumnWidthPercentage.Add(headerText, percentage);
}
void
radGridView1_CellFormatting(
object
sender, CellFormattingEventArgs e)
{
var grid = radGridView1;
var column = e.CellElement.ColumnInfo;
var text = e.CellElement.Text;
if
(
string
.IsNullOrEmpty(text))
{
return
;
}
var maxPercentage = maxColumnWidthPercentage.ContainsKey(column.HeaderText) ? maxColumnWidthPercentage[column.HeaderText] : 0;
var maxWidth = grid.ClientSize.Width * maxPercentage / 100;
if
(dictionary[column.HeaderText].Length <= text.Length && maxPercentage != 0 && column.MinWidth < maxWidth || maxPercentage != 0 && column.MinWidth > maxWidth)
{
dictionary[column.HeaderText] = text;
var requiredWidth = (
int
)(
this
.CreateGraphics().MeasureString(text,
this
.Font).Width + 8);
column.MinWidth = requiredWidth <= maxWidth ? requiredWidth : maxWidth;
column.MaxWidth = column.MinWidth;
column.Width = column.MaxWidth;
}
}
void
radGridView1_DataBindingComplete(
object
sender, GridViewBindingCompleteEventArgs e)
{
var grid = sender
as
RadGridView;
var dateTimeColumm = grid.Columns[1]
as
GridViewDateTimeColumn;
dateTimeColumm.FormatString =
"{0:MM/dd/yy}"
;
dateTimeColumm.Format = DateTimePickerFormat.Short;
foreach
(var column
in
grid.Columns)
{
dictionary.Add(column.HeaderText,
string
.Empty);
//column.MinWidth = (int)(this.CreateGraphics().MeasureString(text, this.Font).Width + 8);
//column.MaxWidth = column.MinWidth;
//column.Width = column.MaxWidth;
}
}
}
public
class
Test
{
public
Test()
{
}
public
decimal
Id {
get
;
set
; }
public
DateTime Date {
get
;
set
; }
public
string
Text {
get
;
set
; }
}
public
class
TestsCollection : BindingList<Test>
{
public
TestsCollection(
int
noItems)
{
for
(
decimal
i = 10000000000000; i < noItems + 10000000000000; i++)
{
this
.Add(
new
Test
{
Id = i,
Date = DateTime.Now.AddDays((
double
)(i % 17)),
Text =
"text"
+ i.ToString()
});
}
}
}
But this will be have a great impact on performance because on size change i have to call a refresh in order for the grid to recalculate the columns.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
In the CellFormatting event, this appears to be set to the design time size, not the runtime size.
For example, I build the form at design time and make the grid 900 wide. At runtime, the grid is set to fill the form and the form is resizable. So the user may have it set to 450 wide.
When the CellFormatting event is executed, the grid width is being calculated based on the 900 instead of the 450.
So I am currently working on shifting the calculations into the Resize event, when the grid width seems to be correctly set to 450. However, this is causing other problems in that it generates more formatting events that then resize the columns back to there original size (not the percentage).
Does this make my problem a little more clear? What happens with your code if you make the grid really small or really large at design time. Does it appear correctly at run time?
I'm not using the designer, i prefer doing thing in code, i had a lot of problems in the past with lost values and serialization data lost, so i did everything by code, so that you can be able to test it, with just copy and paste into an empty project, if you want me to convert it to VB please let me know, but i guess you can use the telerik code converter as well.
The only thing i had to add which i don't really like is calling a refresh on the SizeChanged event, to force a recalculation of the maxWidth of the columns, but please try it for yourself and let me know.
Best Regards,
Emanuel Varga
My Cell Formatting then ended up like this:
Private
Sub
SCStarDataGrid_CellFormatting(
ByVal
sender
As
Object
,
ByVal
e
As
Telerik.WinControls.UI.CellFormattingEventArgs)
Handles
Me
.CellFormatting
Dim
column
As
GridViewColumn = e.CellElement.ColumnInfo
Dim
cellText
As
String
= e.CellElement.Text
' If the cell has wrapped text, ignore it.
' If the cell is empty, ignore it.
If
Not
column.WrapText
AndAlso
Not
String
.IsNullOrWhiteSpace(cellText)
Then
Dim
columnSize =
CType
(
Me
.CreateGraphics.MeasureString(cellText,
Me
.Font).Width,
Integer
) + 5
' Don't set the size larger than the maximum size
If
column.MaxWidth > 0
AndAlso
columnSize > column.MaxWidth
Then
columnSize = column.MaxWidth
End
If
' If the text in this cell is bigger than the longest string for this column, add it to the dictionary.
If
columnSizeDictionary(column.Index) < columnSize
Then
columnSizeDictionary(column.Index) = columnSize
column.MinWidth = columnSize
column.Width = column.MinWidth
End
If
End
If
End
Sub
Notice the extra code to handle the wrapped columns and columns with a defined maximum size.
As per my prior message, I then used the resize event to resize the "fill" column if the other controls don't show all of their contents:
Dim
totalColumnSize
As
Integer
= columnSizeDictionary.Values.Sum()
If
totalColumnSize >
Me
.ClientSize.Width
Then
Dim
fillColumn =
Me
.Columns(FillColumnName)
Dim
fillColumnSize =
Me
.Width - (totalColumnSize - columnSizeDictionary(fillColumn.Index))
columnSizeDictionary(fillColumn.Index) = fillColumnSize
fillColumn.MaxWidth = fillColumnSize
fillColumn.Width = fillColumn.MinWidth
End
If
Notice how this just sets the maxWidth. This prevents the Formatting event from reassigning the size again.
Let me know if you see any issues with this or if there is an easier way.
Thanks again for your help.
In my approach you can define a percentage for the columns you want to limit, and the rest can take / will take all of the remaining space, so you can have more than one fill column.
In my opinion it would offer a more range of usage.
Other than that, i cannot see anything wrong.
Best Regards,
Emanuel Varga
- Set the column width to display its contents.
- If the column width is too long and the defined text field can be wrapped, set it to wrap.
- If the column width is too long and the defined text field cannot be wrapped (by UI design decision), truncate the field to fit.
This worked great when using the Microsoft DataGridView because you could define one column as the Fill column and it took care of everything else for you.
I don't want to add the extra work for each developer to define percentages for all of their grids when the above rules match to our application. Plus, defining the columns as percentages could cause further problems because some fields *must* appear in their entirety (per the UI design).
If these rules change at some future point, I will be back to copy your code instead.
Thanks again for all of your help!
But I am *very* impressed by the level of support Telerik provides.
Thanks again!
As for the support, for me it's a great way of keeping my mind sharp and helping others if and when i can. ;)
P.S. if i remember correctly, you created one or more threads with calculating widths of some specific column types, can you at please close those, and maybe redirect other people who might be interested to this thread?
Once again, always glad to help, and like always if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
Do you want me to start a new thread, or continue this one to explain the problem?
Didn't i already answered the Horizontal Scroll problem in this thread ?
Or is it another scrolling issue?
Best Regards,
Emanuel Varga
if you want to manually implement a glued column, you can append this function to your RadGridView's Resize event
private
void
FitColumns(
object
sender, EventArgs e)
{
// get out if working base is not given
var grid = sender
as
RadGridView;
if
(grid ==
null
|| !grid.Rows.Any())
return
;
// Set this property to prevent BestFitColumns() from shrinking columns whose cells don't
// contain values to a minimum. I know there was some fitting style thing (HeaderCells
// or something) but I fogot what it was, so this basically works fine too
grid.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.None;
// Then call BestFitColumns(), it does almost all the resizing work for you
// well, except glueing columns
grid.BestFitColumns();
// Now that all columns are best fitted, let's see if there is still space after the last column
var visibleColumns = grid.Columns.Where(c => c.IsVisible);
var parentWidth = grid.Parent.Width;
var sumVisisbleColumnsWidth = visibleColumns.Sum(c => c.Width);
var emptySpace = parentWidth - sumVisisbleColumnsWidth;
if
(emptySpace > 0)
{
// If so, modify the width of our glued column
// In this example, the last Column is glued column
visibleColumns.Last().Width += emptySpace;
}
}
I hope this helps some of you out.
Kind regards,
Oliver
Thank you for writing.
When the AutoSizeColumnsMode is set to Fill the columns will fill the entire available space. And if there is no enough space for the header text it will be truncated. For such cases you can set MinWidth for the columns. For example:
void
Form1_Load(
object
sender, EventArgs e)
{
foreach
(var item
in
radGridView1.Columns)
{
item.MinWidth = 100;
}
}
This way when the form size is smaller that the total column mininmum size a scrollbar will appear. However I am not sure what is the exact layout behavior that you want to create. So can you please specify your exact goals? This will allow me to provide you with a proper solution for your case.
I hope this will be useful.
Regards,
Dimitar
Telerik