Set boundcolumn width in gridview isn't working - c#

I have a report page that can display two different reports. So I have a GridView with no columns on my aspx page. I am adding 4 BoundFields to the GridView in the button click event handler. The first column is the one I need to set the width of for one of the reports (the code I'm using to add this column is below).
gvReport.Columns.Clear();
BoundField bf1 = new BoundField();
...
if (ddReportType.SelectedValue == "full") {
bf1.HeaderText = "Facility";
bf1.DataField = "Facility";
bf1.ItemStyle.Wrap = true;
bf1.ItemStyle.Width = 150;
bf1.Visible = true;
gvReport.Columns.Add(bf1);
...
The problem is there is one row that has a SHA512 hash in this column. Since there is no space in the middle of it, the gridview won't wrap it (I think that's what is happening, anyway)! So I thought I'd catch this column in the OnRowDataBound event and add a space in the middle of the hash so it will wrap, but I can't figure out how to reference the BoundField. There's no ID property. Does anyone have a suggestion? Either on how to reference the BoundField, or another way to get this to display nicely?
I had the columns in the aspx file originally and tried using:
gvReport.Columns[0].ItemStyle.Width = 150;
gvReport.Columns[0].ItemStyle.Wrap = true;
but that didn't work either. This is very frustrating!

So we went with Plan C. I never did figure out how to reference the BoundField. We got around that problem by creating two GridViews in the markup and just changing which one is visible. To solve the problem of the text that won't wrap, we're catching it in the OnRowDataBound event handler and checking the length of the text. We just insert a space in the middle, and voila! It wraps!

The BoundField is a wrong thing. It is more like a definition. Later, when binding or creating rows, you are dealing with rows, cells, and data items.
You could do something like this:
protected void grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string value = e.Row.Cells[1].Text;
if (!string.IsNullOrEmpty(value))
e.Row.Cells[1].Text = value.Insert(value.Length / 2, " ");
}
}
where Cell[1] is the column containing long values. In the same place, you could use e.Row.DataItem to get actual data, but then you'd need to know its type.
You could create a template field and bind to an expression or use its child's data bound event to do the same.
Also, if you were using a DataSet, you could set up calculated field and bind to it. Anyway...

Related

How to set and get the value of Data Bind Gridview Combobox Column in C#

I have a data grid view with combo box column in it, i have bind that column to datatable like this:
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).DataSource = dt;
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).DisplayMember = "LocationName";
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).ValueMember = "Id";
now i can get the selected value like this:
var value = grdItems.Rows[0][1].Value;
but the issue is, when i manually add the rows in the gridview (without binding the grid), i cant get the value of the combobox cell.
i am adding rows like this:
grdItems.Rows.Add(1, 1, "Some Value");
when i use
var value = grdItems.Rows[0][1].Value;
this method to get the value, i returns me the text of the cell not the value i.e 1 in this case.
How can i solve this issue? since i want the value of the cell in case of adding rows manually, as well as data-bind rows.
Am assuming that by manually adding rows you mean from the UI , so one way to get the value of the newly added row is to use an event handler for the events raised when you add an row. You may use one of the following
1) RowsAdded https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rowsadded(v=vs.110).aspx 2) RowPrePaint - https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rowprepaint(v=vs.110).aspx - not used this much but is also an option
this.myGridView.RowsAdded += new DataGridViewRowsAddedEventHandler(myGridView_RowsAdded);
private void myGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
var newRow = this.myGridView.Rows[e.RowIndex];
}
Edit: Based on the actual requirement stated in the comments - actual requirement being retrieving the newly added row's cell value (Id) corresponding to the combox box column on button save clicked event
Assuming you have bound the combo box to a data source itself , meaning, your
combobox.DataSource=someList
so what you can do is write a linq query
someList.Where( v=>v.Text.Equals("row.Cells[1].Value")).FirstOrDefault().Id

Get the value of a column that is using a ButtonField

I have a GridView and one of the columns has a TemplateField using a LinkButton (ButtonField)
I can get the value of a specific cell in my Grid Just fine. Using:
GridViewRow row = GridView1.SelectedRow;
lblSalesmanCustomers.Text = row.Cells[2].Text;
I then display the text from that cell in a Label.
However I cannot get this to work with a ButtonField Template. It only works with a non Template column.
How can I get the value of a specific cell in a column that is using a ButtonField / TemplateField?
EDIT: This is My Button Field Code inside my GridView:
<asp:ButtonField DataTextField="Customer" HeaderText="Customer" ButtonType="Link" CommandName="Select" />
Also, this is happening in this event:
protected void gvManagerCustomers_SelectedIndexChanged(object sender, EventArgs e)
See if var Button = row.Cells["Customer"].Controls[0]; would retrieve the button you need.
You might need to cast it to the correct type.
I know there are issues with hyperlinkfield and buttonfield but there is a work around. Say you are binding buttonfield text based on a column called ButtonNames, and in that column you have all your names, such as "button bob", "button jerry" etc. In your GridView, add an invisible column as your very first column and bind its value as ButtonNames. You make it invisible by setting one of the visibility properties. Forgot what it was from top of my head. Then, when you want to get the text for the buttonfield simply get the data from that invisible column instead Same applies to hyperlinkfiends.
EDIT: here's some code.
<asp:BoundColumn ItemStyle-HorizontalAlign="Left" DataField="ButtonNames" SortExpression="ButtonNames" HeaderText="TriageId" Visible="false" ReadOnly="true"></asp:BoundColumn>
Then you retrieve it via string s = e.Item.Cells[0].Text where e is a DataGridCommandEventArgs or something to that nature.
There will be a controls collection in the cell - you may be able to access it there.
Though a simpler way would be to use something like:
Label l = row.FindControl("myControlId");
EDIT: true the exact approach above does not work - but you can use the controls, the following does work, note that what we are doing here is pretty much rife with bad practices (but then we are using a GridView for convenience sake after all).
protected void gvManagerCustomers_SelectedIndexChanged(object sender, EventArgs e)
{
var x = ((sender as GridView).SelectedRow.Cells[0].Controls[0] as LinkButton).Text;
}
In order to figure this out set up a debug environment and breakpoint in the handler method then drill down through the class hierarchy. The debugger is our friend ;)
EDIT just to mention the obvious - the column is hard coded here - you will probably have to change it.

Prevent databound DataGridView from sorting while editing

I have a databound DataGridView in a Win Forms app which the user may have sorted by a column. The problem is this: after the user leaves a row after editing a cell in the sorted column, the row is immediately re-sorted.
This is very disorienting for users and makes editing groups of rows together impossible.
The solution I'm looking for will effectively disable automatic re-sorting after an initial sort and then only sort again when the user requests it.
For the benefit of others, here is the solution I came up with, but I'd love to hear a better one.
I added an additional, non-persistent column to the DataTable called SORT_ORDER which is used only for sorting.
When the user clicks a column to sort, I copy the values and value type from the selected column to the SORT_ORDER column and then sort on SORT_ORDER. Since the SORT_ORDER is not visible and can't be edited, the sort order does not change even if the user edits the selected column. The event handler looks like this:
private void MyDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
dirtyCellListenerEnabled = false;
SORT_ORDER.ValueType = MyDataGridView.Columns[e.ColumnIndex].ValueType;
foreach(DataGridViewRow r in MyDataGridView.Rows) {
r.Cells[SORT_ORDER.Index].Value = r.Cells[e.ColumnIndex].Value;
}
switch(MyDataGridView.SortOrder) {
case System.Windows.Forms.SortOrder.None:
MyDataGridView.Sort(SORT_ORDER, ListSortDirection.Ascending);
break;
case System.Windows.Forms.SortOrder.Ascending:
MyDataGridView.Sort(SORT_ORDER, ListSortDirection.Descending);
break;
case System.Windows.Forms.SortOrder.Descending:
MyDataGridView.Sort(SORT_ORDER, ListSortDirection.Ascending);
break;
}
dirtyCellListenerEnabled = true;
}
Note that I had to disable and re-enable my cell listener so that my code doesn't treat the sort column update as a real change.
Before arriving at this solution, I had also tried adding the sort column to the DataGridView, but it doesn't work because the DataGridView can't sort on a column that doesn't exist in its data source.
I'm sure there are some other tweaks I could do, too, like suspending updates while populating the SORT_ORDER and displaying the sort glyph on the selected column.
This is a real pain as i'm finding out right now. Grids are brutally complicated sometimes for seemingly nothing
for each selected cell, I store the primary key, and the name of the grid column (i made a tiny class to hold those).
Then I throw them all into a list and iterate through them for the updating. Each time I update a cell value, i search for where the actual cell is now and replace my local reference variable to that cell so I can keep going in the code.
Cell.Value = ValueToWrite
Cell = FindCell(Cell.OwningRow.DataGridView, DataRow, ColName)
Function FindCell(Grid As DataGridView, DataRow As DataRow, ColName As String) As DataGridViewCell
'Find the same cell, wherever you may be now, damn you sort.
Dim GridRow = (From x As DataGridViewRow In Grid.Rows Where x.DataBoundItem.row Is DataRow).FirstOrDefault
Dim Cell = GridRow.Cells(ColName)
Return Cell
End Function
I've encountered this problem and couldn't get a decent answer, so I tried this and it worked,
private void SortBoundDG()
{
DataTable TempTable;
TempTable = (DataTable)DG.DataSource;
TempTable.DefaultView.Sort = ColumnName + " " + "DESC";
DG.DataSource = TempTable.DefaultView.ToTable();
}
simply convert the defaultview back to a table and set it as a source to your datagridview
Sounds like your GridView is data binding all over again. This means that your sort order will be lost. Enable the Viewstate of your gridview and make sure that you aren't binding the grid on postback.

Gridview making a column invisable

Hi I have a grid view which is dynamically generated via C# using a DataSet.
I'm passing a row ID field (from the database) to the grid view, as this is required when a user clicks to edit a records. However I don't want the user to be able to view the column.
I have tried the following but it doesn’t seem to work? Could anyone suggest a way to hide the column or a better way of attaching the information to the grid view row so it can be used at a later stage.
c#
DataColumn ColImplantCustomerDetailsID = new DataColumn();
ColImplantCustomerDetailsID.ColumnName = "Implant ID";
ColImplantCustomerDetailsID.DataType = typeof(int);
ColImplantCustomerDetailsID.Visable = false; <-- visable doens't work here.
asp.net
DataColumn doesn't have a 'Visable' property. Heck, it doesn't have a 'Visible' property either.
Use this before you bind
gridviewNameHere.Columns[index].Visible = false;
You can make it visible again on one of your event handlers.
Another option, rather than hiding the column, is to use the DataKeyNames property of the GridView to store the name of the ID field. You can then use myGridView.SelectedValue to retrieve the selected ID.
Use the index of the column to hide it when you initialize it...
grid.Columns[index].Visible = false;
I actually hide a few things as you are suggesting, example - database status names for that row that can be used in code that the user does not need to see.
Accessing GridView Invisible Columns
http://www.highoncoding.com/Articles/178_Access_GridView_Invisible_Columns.aspx
In the OnRowDataBound event of the GridView component:
// c#
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
int index = 0; // put the index of the column you need hide.
e.Row.Cells[index].Visible = false;
}

C# Add HyperLinkColumn to GridView

I'm trying to add HyperLinkColumns dynamically to my GridView. I have the following code:
HyperLinkColumn objHC = new HyperLinkColumn();
objHC.DataNavigateUrlField = "title";
objHC.DataTextField = "Link text";
objHC.DataNavigateUrlFormatString = "id, title";
objHC.DataTextFormatString = "{2}";
GridView1.Columns.Add(objHC);
This doesn't work, so.. how can i add a HyperLinkColumn to my GridView?
You might want to add it when the row is binded:
protected void yourGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
HyperLink hlControl = new HyperLink();
hlControl.Text = e.Row.Cells[2].Text; //Take back the text (let say you want it in cell of index 2)
hlControl.NavigateUrl = "http://www.stackoverflow.com";
e.Row.Cells[2].Controls.Add(hlControl);//index 2 for the example
}
You have to do it before the DataBinding takes place, check the GridView Events.
I think you should be using a HyperLinkField not a HyperLinkColumn.
In case, if you just want to redirect to another URL then simple use HyperLink web control and push it in the desired cell of GridView Row at RowDataBound event.
OR
If you want to perform any server event before sending it to another URL, try this
1) Add LinkButton object at RowDataBound event of GridView.
2) Set the CommandName, CommandArgument property, if requried to pass any data to this object.
3) Capture this event by handling the RowCommand event of the GridView.
By the way, I just think that you can use the DataGridView and in the Designer select the Link column and your problem would be over. The DataGridView does have a link column, than you just need to add an event on "Click" and you will be able to have what you want. This solution works if you can switch to DataGridView.
I know this thread is old but couldn't help adding my 2 cents. The procedure explained in the following tutorial worked perfectly for me:
ASP Alliance
It seems you have got things mixed up. I don't know - how that code compiles?
GridView's column collection can accept columns of type "DataControlField".
I think you need to initialize HyperLinkField and set relevant properties (text, NavigateUrl, HeaderText, Target) and add it to the columns collection.
HyperLinkColumn class is meaningful when you are using DataGrid (not in case of GridView).
Hope that helps.

Categories

Resources