How to Set a gridview column width when binding to a datatable - c#

I am binding a table to a gridview in asp.net as such
grdIssues.DataSource = mdtIssues;
grdIssues.DataBind();
The problem is I cannot then control the column width, asp.net seems to decided on it's own what width each column should be. Methods such as
grdIssues.Columns[0].ItemStyle.Width = 100;
grdIssues.Columns[1].ItemStyle.Width = 100;
don't work because the columns are created dynamically. I cannot believe there isn't a way to do this short of manually creating each column and filling each row.

You dont have to manually create the columns to set them the width, you can do this
foreach (DataControlField column in OrdersGV.Columns)
{
column.ItemStyle.Width = Unit.Pixel(100);
}

I was able to change the width of a certain Gridview column (bound to a Datatable) with the RowDataBound event:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) {
e.Row.Cells[0].Attributes["width"] = "200px";
}

I like to answer my own question whenever I can so future users searching the thread will find the answer.
I could not find a way to do what I wanted directly. However I found if I define the columns myself, I could change the properties. In this example, I wanted to center the column data. Something like this.
BoundField bdfRaisedDate = new BoundField();
clsUtilities.SetBoundFieldCenter(ref bdfRaisedDate, "RaisedDateShort", "Opened", "RaisedDate");
grdIssues.Columns.Add(bdfRaisedDate);
grdIssues.DataSource = mdtIssues;
grdIssues.DataBind();
public static void SetBoundFieldCenter(ref BoundField bdfAny, string pDataField, string pHeadingValue, string pSortExpression)
{
bdfAny.DataField = pDataField;
bdfAny.HeaderText = pHeadingValue;
bdfAny.SortExpression = pSortExpression;
bdfAny.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
bdfAny.ItemStyle.HorizontalAlign = HorizontalAlign.Center;
}

I did it as:
gridView1.HeaderRow.Cells[0].Attributes["Width"] = "100px";
gridView1.HeaderRow.Cells[1].Attributes["Width"] = "50px";
gridView1.HeaderRow.Cells[2].Attributes["Width"] = "200px";

I'd do it like this:
foreach (DataControlField field in grdIssues.Columns)
{
field.HeaderStyle.Width = 100;
}

Related

DataGridView and SQL query name

I have a function that gets all the data from database (also the column names) and shows it in a DataGridView.
The problem is that the DataGrid show also the column name. How can I edit the columns name? I already tried
dataGridView1.Columns[0].Name = "xxx";
without success.
private void PriceChange_Load(object sender, EventArgs e)
{
DbCards d = new DbCards();
dataGridView1.DataSource = d.GetAllcards().Tables[0];
}
GetAllcards() is select * from Cards.
If you want to change the header text displayed by a DataGridViewColumn you need to use the HeaderText property
dataGridView1.Columns[0].HeaderText = "xxx";
Set dataGridView1.Columns[0].HeaderText instead

Using C# to set System.Drawing.Color.FromName

Objective: The objective is to set the System.Drawing.Color dynamically based on a text value within a datatable. The text value is the name of a color within System.Drawing.Color. The purpose is to change the backcolor of a grid based on the given value.
Issue: The method I am using now does not obtain a value from the datatable and sets the Color to 0,0,0,0. The datatable is created using a ViewState. The research I've conducted on this issue indicates this should work. However, the value obtained from the DataTable is "" . What is incorrect in this code? Thank you in advance for you comments, suggestions and consideration. The code is as follows:
DataTable code
private void CreateList()
{
DataTable dtMyList = new DataTable();
DataColumn dcID = new DataColumn("ID");
dtMyList.Columns.Add(dcID);
DataColumn dcColor = new DataColumn("Color");
dtMyList.Columns.Add(dcColor);
ViewState["MyList"] = dtMyList;
}
On RowDataBound code intended to change the backcolor
protected void grdMyList_RowDataBound(object sender, GridViewEventsArgs e)
{
DataTable dtMyList = (DataTable)ViewState["MyList"];
for (int i = 0; i < dtMyList.Rows.Count; i++)
{
e.Row.Cells[0].BackColor = System.Drawing.Color.FromName(Convert.ToString(dtMyList.Rows[0]["Color"]));
}
}
First of all: Is the datatable filled with any data?
Second: you are trying to fill that one row (given in the event args) with all the colors from the datatable, resulting in that only one property (e.Row.Cells[0].BackColor) is filled with the color coming from the last row in the table (dtMyList.Rows[i]["Color"]).
I think you should first lookup the correct datarow which is attached to your gridrow (e.Row.DataItem), then read its color and then fill the property of your gridrow. Like this:
protected void grdMyList_RowDataBound(object sender, GridViewEventsArgs e)
{
DataRow row = (DataRow)e.Row.DataItem;
e.Row.Cells[0].BackColor = System.Drawing.Color.FromName(row["Color"].ToString());
}
You're looping through the entire table and setting the color for each row. I think you want something like
protected void grdMyList_RowDataBound(object sender, GridViewEventsArgs e)
{
DataTable dtMyList = (DataTable)ViewState["MyList"];
index i = e.Row.RowIndex;
e.Row.Cells[0].BackColor = System.Drawing.Color.FromName(Convert.ToString(dtMyList.Rows[i]["Color"]));
}

C# DataGridView: Value disappearing in dynamic added column

I am coming across something strange or maybe it is the way it works and its just my lack of understand of how the datagridview works. I am dynamically adding a column when I click on a button
private void btnAssign_Click(object sender, EventArgs e)
{
if (!gvData.Columns.Contains("DepartmentId"))
{
DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
DataGridViewColumn dc = new DataGridViewColumn();
dc = new DataGridViewTextBoxColumn();
dc.HeaderText = "DepartmentId";
dc.Name = "DepartmentId";
dc.CellTemplate = cell;
gvData.Columns.Add(dc);
}
foreach(DataGridViewRow row in gvData.SelectedRows)
{
row.Cells["DepartmentId"].Value = getSelectedValues(clbDept);
}
}
first it checks if the DepartmentId column is in the datagridview (dgv). If not then I create a new Datagridviewtextboxcolumn and sets the appropriate settings. Then adds values to the cells. SO far so good... this where is does weird things... when I sort another column, the data in the 'DepartmentId' column disappears. Data disappears in the columns that I dynamically create. Do i have to use a save method or something?
Instead of adding data directly to datagridview you need to add column to datasource and reassign the datasource to datagridview. This will resolve your sorting issue.

oldvalues of SqlDatasource for dynamic gridview-templates

For a dynamic Gridview i am generating columns at runtime like this:
TemplateField tf = new TemplateField();
tf.HeaderText = colName;
tf.ItemTemplate = new GenericItem(ListItemType.Item, colName, "Command");
tf.EditItemTemplate = new GenericItem(ListItemType.EditItem,
Gridview1.Columns.Add(tf);
The GenericItem implements IBindableTemplate:
public class GenericItem : IBindableTemplate
This works fine, but when i am trying to update some columns, i need to have access to the old values. I assumed i could just use this:
<asp:SqlDataSource runat="server" ID="dsGridview" OldValuesParameterFormatString="old_{0}" ConflictDetection="CompareAllValues" />
But when i want to access the oldvalues property of my datasource in the RowUpdating event of the Gridview i noticed that the oldvalues collection is empty (the newvalues collection is filled just fine)
Does anybody know how i can get those oldvalues?
Best regards,
r3try
ok, this is not how i wanted to solve it - but as there are no other suggestions here is how i worked around my problem. Maybe someone else has the same problem:
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
//GET THE OLD VALUES
myOldValues.Clear();
GridView gv = (GridView)sender;
gv.EditIndex = e.NewEditIndex;
gv.DataBind();
//populate
for (int i = 0; i < Gridview1.Columns.Count; i++)
{
DataControlFieldCell cell = gv.Rows[e.NewEditIndex].Cells[i] as DataControlFieldCell;
gv.Columns[i].ExtractValuesFromCell(myOldValues, cell, DataControlRowState.Edit, true);
}
Session["MyOldValues"] = myOldValues;
}

How to hide column of DataGridView when using custom DataSource?

I have a small app in c#, it has a DataGridView that gets filled using:
grid.DataSource = MyDatasource array;
MyClass hold the structure for the columns, it looks something like this:
class MyDatasource
{
private string column1;
private string column2;
public MyDatasource(string arg1, string arg2)
{
this.column1 = arg1;
this.column2 = arg2;
}
public string column1
{
get
{
return this.column1;
}
set
{
this.column1 = value;
}
}
public string column2
{
get
{
return this.column2;
}
set
{
this.column1 = value;
}
}
}
Everything works fine and the DataGridView gets populated with the correct data, but now I want to hide the column2. I tried adding [Browsable(false)] above the column declaration, that will hide it, but I also need to access the column value from code, and when I use [Browsable(false)] and try to read the content it acts like if the column doesn't exist. If I don't use it I can read the column without problem but it's visible in the DataGridView.
How could I hide the column but still be able to read its content from code?
In some cases, it might be a bad idea to first add the column to the DataGridView and then hide it.
I for example have a class that has an NHibernate proxy for an Image property for company logos. If I accessed that property (e.g. by calling its ToString method to show that in a DataGridView), it would download the image from the SQL server. If I had a list of Company objects and used that as the dataSource of the DataGridView like that, then (I suspect) it would download ALL the logos BEFORE I could hide the column.
To prevent this, I used the custom attribute
[System.ComponentModel.Browsable(false)]
on the image property, so that the DataGridView ignores the property (doesn't create the column and doesn't call the ToString methods).
public class Company
{
...
[System.ComponentModel.Browsable(false)]
virtual public MyImageClass Logo { get; set;}
You have to hide the column at the grid view control rather than at the data source. Hiding it at the data source it will not render to the grid view at all, therefore you won't be able to access the value in the grid view. Doing it the way you're suggesting, you would have to access the column value through the data source as opposed to the grid view.
To hide the column on the grid view control, you can use code like this:
dataGridView1.Columns[0].Visible = false;
To access the column from the data source, you could try something like this:
object colValue = ((DataTable)dataGridView.DataSource).Rows[dataSetIndex]["ColumnName"];
I have noticed that if utilised progrmmatically it renders incomplete (entire form simply doesn't "paint" anything) if used before panel1.Controls.Add(dataGridView); then dataGridView.Columns["ID"].Visible = false; will break the entire form and make it blank, so to get round that set this AFTER EG:
panel1.Controls.Add(dataGridView);
dataGridView.Columns["ID"].Visible = false;
//works
dataGridView.Columns["ID"].Visible = false;
panel1.Controls.Add(dataGridView);
//fails miserably
I"m not sure if its too late, but the problem is that, you cannot set the columns in design mode if you are binding at runtime. So if you are binding at runtime, go ahead and remove the columns from the design mode and do it pragmatically
ex..
if (dt.Rows.Count > 0)
{
dataGridViewProjects.DataSource = dt;
dataGridViewProjects.Columns["Title"].Width = 300;
dataGridViewProjects.Columns["ID"].Visible = false;
}
Set that particular column's Visible property = false
dataGridView[ColumnName or Index].Visible = false;
Edit
sorry missed the Columns Property
dataGridView.Columns[ColumnName or Index].Visible = false;
I had the same problem
Here is the Solution that might work for you. It worked for me
GridView1.DataBind();
if (GridView1.Columns.Count > 0)
GridView1.Columns[0].Visible = false;
else
{
GridView1.HeaderRow.Cells[0].Visible = false;
foreach (GridViewRow gvr in GridView1.Rows)
{
gvr.Cells[0].Visible = false;
}
}
Just set DataGridView.AutoGenerateColumns = false;
You need click on the arrow on top right corner (in datagridview) to add columns, and in DataPropertyName you need to put a name of your property in your class.
Then, after you defined your columns in datagridview, you can set datagridview.datasource = myClassViewModel.
MyDataGridView.RowHeadersVisible = False;
Before binding and rename each columns header and set columns width.
To help my failing memory when I search, because I will search ... that's for sure ;-)
If you want to use the BrowsableAttribute, then you can look for it at runtime on the model and hide the column accordingly:
private void Form_Load(object sender, EventArgs e)
{
//add this line after your DataGridView initialization
HideColumns<MyModel>(myDvg);
}
private void HideColumns<T>(DataGridView dvg)
{
var type = typeof(T);
foreach (var column in dvg.Columns.Cast<DataGridViewColumn>())
column.Visible = IsBrowsable(type.GetProperty(column.Name));
}
private bool IsBrowsable(PropertyInfo propertyInfo)
{
var attribute = propertyInfo.GetCustomAttributes(true).FirstOrDefault(att => att.GetType() == typeof(BrowsableAttribute));
return attribute == null || (attribute as BrowsableAttribute).Browsable;
}
Try follow:
DataGridView1.Columns["YourColumnName"].Visible = false;

Categories