I have a function in my code-behind that sets a datagrid. I create a new blank column and add it to my datagrid and I want to add a value to the column for only one row that matches an object id. For some reason the cell doesn't store the text I set it to though. Any thoughts?
public void SetContacts(IEnumerable<User> contactList, User reqUser)
{
BoundColumn reqColumn = new BoundColumn();
reqColumn.HeaderText = "";
dgExistingContacts.Columns.Add(reqColumn);
dgExistingContacts.DataSource = contactList;
foreach (DataGridItem row in dgExistingContacts.Items)
{
if (row.Cells[0].Text == reqUser.id.ToString())
row.Cells[6].Text = "Requestor";
}
dgExistingContacts.DataBind();
}
Here's my datagrid if that helps:
<asp:DataGrid runat="server" ID="dgExistingContacts" AutoGenerateColumns="false" CssClass="styledGray" HeaderStyle-CssClass="head" CellSpacing="1" CellPadding="4" GridLines="None" AlternatingItemStyle-CssClass="even" ItemStyle-CssClass="odd">
<Columns>
<asp:BoundColumn DataField="Id" Visible="false" />
<asp:BoundColumn DataField="Title" HeaderText="Role" />
<asp:BoundColumn DataField="LastName" HeaderText="Last Name" ItemStyle-Wrap="false" />
<asp:BoundColumn DataField="FirstName" HeaderText="First Name" ItemStyle-Wrap="false" />
<asp:BoundColumn DataField="Phone" HeaderText="Phone" DataFormatString="{0:(###) ###-####}" />
<asp:BoundColumn DataField="EmailAddress" HeaderText="Email" ItemStyle-Wrap="false" />
</Columns>
</asp:DataGrid>
I feel like it should be simple but I can't figure out why it's not binding.
Try handling the GridView's RowDataBound event and adding the value there.
As I see you are adding a column to dgExistingContacts and then assign contactList as DataSource of dgExistingContacts that means you first add column and then reset DaraGrid to former DataSource in this code:
dgExistingContacts.Columns.Add(reqColumn);
dgExistingContacts.DataSource = contactList;
I think when you assign a DataSource to GridView,any thing that you changed in it will be reseted.so maybe by deleting dgExistingContacts.DataSource = contactList;from codes, your problem will be solved.
I figured out that you have to bind the data before trying to change the contents. I ended up with this:
public void SetContacts(IEnumerable<User> contactList, User reqUser)
{
BoundColumn reqColumn = new BoundColumn();
reqColumn.HeaderText = "";
dgExistingContacts.Columns.Add(reqColumn);
dgExistingContacts.DataSource = contactList;
dgExistingContacts.DataBind();
foreach (DataGridItem row in dgExistingContacts.Items)
{
if (row.Cells[0].Text == reqUser.id.ToString())
row.Cells[6].Text = "Requestor";
}
}
Related
I'm currently working on an in house project, I've created a GridView connected to a SQL table which looks like this:
GridView1
I created the view content buttons using the following code:
<Columns>
<asp:ButtonField ButtonType="Button" Text="View Content" CommandName="Select" />
<asp:BoundField DataField="ContentID" HeaderText="ContentID" InsertVisible="False" ReadOnly="True" SortExpression="ContentID" />
<asp:BoundField DataField="Code" HeaderText="Code" SortExpression="Code" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:BoundField DataField="URL" HeaderText="URL" Visible="true" SortExpression="URL" />
</Columns>
But this is where I am now stuck. I would like to click on the view content button and have it navigate to the URL on the selected row.
The URL comes from the SQL Table and there is a string so I'd imagine, it would need to be converted first but I could be wrong.
I started to put my code in the following:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewCommandEventArgs x = (GridViewCommandEventArgs)e;
if (x.CommandName == "Select")
{
GridViewRow row = GridView1.SelectedRow;
}
}
Add your code in GridView1_RowCommand event of gridview:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
GridViewRow row = (GridViewRow)(((BoundField)e.CommandSource).NamingContainer);
int index = row.RowIndex;
string url = (GridView1.Rows[index].FindControl("URL") as BoundField).Text;
Response.Redirect(url); // url can be from your sql table
}
}
Note: Don't forget to add OnRowCommand event in GrindView <asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand" >
GridViewRow row = (GridViewRow)(((BoundField)e.CommandSource).NamingContainer);
int index = row.RowIndex;
string url = (GridView1.Rows[index].FindControl("URL") as BoundField).Text;
Response.Redirect(url); // url can be from your sql table
So i made the change. Unfortunately, BoundField does not contain a definition for NamingContainer.
Also, GridView1.Rows[index].FindControl("URL") as BoundField fails due to the following error, cannot convert type 'system.web.ui.control' to 'system.web.ui.webcontrols.boundfield' via a reference conversion, boxing conversion, unboxing conversion or null type conversion.
I`m having problems with my GridView control. I can not manage to keep my css class on the sorted header after a post sorting DataBind.
My GridView:
<asp:GridView CssClass="grid-view shadow" ID="GridView1" runat="server" Caption="Application Owners" AutoGenerateColumns="false" PageSize="10" ShowHeaderWhenEmpty="true" EmptyDataText="No information found." AllowSorting="true" AllowPaging="true" OnSorting="GridView1_Sorting" >
<PagerSettings FirstPageText="First" PreviousPageText="Previous" NextPageText="Next" LastPageText="Last" Visible="False" />
<HeaderStyle CssClass="header" />
<FooterStyle ForeColor="MediumBlue" BackColor="LightCyan" />
<RowStyle CssClass="odd-row" />
<AlternatingRowStyle CssClass="even-row" />
<SortedAscendingHeaderStyle CssClass="sort-asc" />
<SortedDescendingHeaderStyle CssClass="sort-desc" />
<Columns>
<asp:BoundField DataField="ClientName" HeaderText="Client" SortExpression="ClientName" />
<asp:BoundField DataField="CompanyName" HeaderText="Company" SortExpression="CompanyName" />
<asp:BoundField DataField="HostName" HeaderText="HostName" SortExpression="HostName" />
<asp:BoundField DataField="InstanceName" HeaderText="Instance" SortExpression="InstanceName" />
<asp:BoundField DataField="SystemType" HeaderText="SystemType" SortExpression="SystemType" ItemStyle-Wrap="True" />
<asp:BoundField DataField="DatabaseName" HeaderText="Database" SortExpression="DatabaseName" />
<asp:BoundField DataField="BackupStrategyName" HeaderText="Strategy" SortExpression="BackupStrategyName" />
<asp:BoundField DataField="BackupType" HeaderText="Type" SortExpression="BackupType" />
<asp:BoundField DataField="BackupLocation" HeaderText="Location" SortExpression="BackupLocation" />
<asp:BoundField DataField="EngineName" HeaderText="Engine" SortExpression="EngineName" />
<asp:BoundField DataField="Comments" HeaderText="SequenceType" SortExpression="Comments" />
<asp:BoundField DataField="LastModified" HeaderText="LastModified" SortExpression="LastModified" />
</Columns>
</asp:GridView>
Since I`m using a DataTable as a source, I apply the sort expression to it and rebind it to my GridView using its property GridView1.DefaultView.
My Sorting method:
public void GridViewSort(object sender, GridViewSortEventArgs e)
{
SortDirection _sortDirection;
SortDirection _lastSortDir = SortDirection.Ascending;
string _sortDir;
string _cssClass;
int _columnIndex = 0;
// Get the last sort direction from the DataTable`s DefaultView property.
if (tempTable.DefaultView.Sort.ToString().Contains("ASC"))
{
_lastSortDir = SortDirection.Ascending;
}
else if (tempTable.DefaultView.Sort.ToString().Contains("DESC"))
{
_lastSortDir = SortDirection.Descending;
}
// Check if it`s the first time sorting the GridView.
if (String.IsNullOrEmpty(tempTable.DefaultView.Sort.ToString()))
{
_sortDirection = SortDirection.Ascending;
}
else
{
// If the sort is on the same column as the previous sort then change the sorting order.
if (tempTable.DefaultView.Sort.ToString().Contains(e.SortExpression.ToString()))
{
_sortDirection = (_lastSortDir == SortDirection.Ascending) ? SortDirection.Descending : SortDirection.Ascending;
}
// If it`s a different column then sort it in Ascending order.
else
{
_sortDirection = SortDirection.Ascending;
}
}
// Set the DefaultView.Sort propery of the DataTable and rebind it to the GridView.
// Add the sort oreder icon to the filtered header.
_sortDir = (_sortDirection == SortDirection.Ascending) ? "ASC" : "DESC";
_cssClass = (_sortDirection == SortDirection.Ascending) ? "sort-asc" : "sort-desc";
tempTable.DefaultView.Sort = e.SortExpression.ToString() + " " + _sortDir.ToString();
GridView1.DataSource = tempTable;
GridView1.DataBind();
// Find GridView header and add sorting image class
foreach (DataControlFieldHeaderCell headerCell in GridView1.HeaderRow.Cells)
{
if (headerCell.ContainingField.SortExpression == e.SortExpression)
{
_columnIndex = GridView1.HeaderRow.Cells.GetCellIndex(headerCell);
}
}
GridView1.HeaderRow.Cells[_columnIndex].CssClass = _cssClass;
}
Until this point it works like a charm. My problem is that when I go to the next page or do any action that needs a new DataBind() to the GridView the css class of the header gets removed. I'm relatively new to C# so I don't know how to work with view state if that is a possible solution. Thank you!
<asp:HyperLinkField DataNavigateUrlFields="runId" DataTextField="Percent" ControlStyle-CssClass="hlink" HeaderText="% SEEN" ItemStyle-Width="6%" DataNavigateUrlFormatString="run.aspx?runId={0}" ItemStyle-Font-Underline="true"/>
The above is a column from my grid view.Lets call this column 'x'.
I am trying to control the value of x in .cs file as below:
protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.Cells[8].Text.Equals("0"))
{
e.Row.Cells[13].Text = "0%";
return;
}
int p,q;
GridViewRow item = e.Row;
SqlConnection con = new SqlConnection(connectionstring.ToString());
string selectSQL = " SELECT COUNT(*) AS 'Count' FROM Analysed WHERE runId =#myvar group by runId";
SqlCommand cmd = new SqlCommand(selectSQL, con);
cmd.Parameters.AddWithValue("#myvar", item.Cells[0].Text);
SqlDataReader reader;
try
{
con.Open();
Int32.TryParse(item.Cells[8].Text, out p);
reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
Int32.TryParse( reader["Count"].ToString(),out q);
item.Cells[13].Text =(q/p).ToString() + "%";
}
reader.Close();
}
}
I get an exception saying "An exception of type 'System.ArgumentOutOfRangeException' occurred in System.Web.dll but was not handled in user code Additional information: Specified argument was out of the range of valid values".This occurs in the lines :
if (e.Row.Cells[8].Text.Equals("0"))
{
e.Row.Cells[13].Text = "0%";
return;
}
Can anyone help ?
EDIT :
GridView Code :
<asp:GridView ID = "GridView2" runat = "server" HorizontalAlign="Center"
DataSourceID = "source" AutoGenerateColumns = "False" AllowPaging="True" OnRowDataBound="GridView2_RowDataBound">
<Columns>
<asp:HyperLinkField DataNavigateUrlFields="runId" DataTextField="runId" HeaderText = "RUN ID" ControlStyle-CssClass="hlink" DataNavigateUrlFormatString="runanalysis.aspx?runId={0}" ItemStyle-Width="5%" ItemStyle-Font-Underline="true" />
<asp:HyperLinkField DataField="link" HeaderStyle-ForeColor="White" HeaderStyle-Font-Underline="true" ItemStyle-Width="10%" ItemStyle-Font-Underline="true"/>
<asp:BoundField DataField="Family" HeaderText="Product Family" ItemStyle-Width="7%" />
<asp:BoundField DataField = "Date" DataFormatString="{0:MM/dd/yy}" ItemStyle-Width="7%"/>
<asp:BoundField DataField = "Number" ItemStyle-Width="5%"/>
<asp:BoundField DataField = "Total" ItemStyle-Width="7%" />
<asp:BoundField DataField="Pass" ItemStyle-Width="7%" HeaderText="Pass Percent" DataFormatString="{0}%" />
<asp:BoundField DataField="pass" ItemStyle-Width="7%"/>
<asp:BoundField DataField="fail" ItemStyle-Width="7%"/>
<asp:BoundField DataField="Owner" ItemStyle-Width="7%"/>
<asp:BoundField DataField="Lang" ItemStyle-Width="5%"/>
<asp:BoundField DataField="Plat" ItemStyle-Width="7%"/>
<asp:BoundField DataField="Flavor" ItemStyle-Width="7%"/>
<asp:HyperLinkField DataNavigateUrlFields="runId" DataTextField="Percent" ControlStyle-CssClass="hlink" HeaderText="% SEEN" ItemStyle-Width="6%" DataNavigateUrlFormatString="run.aspx?runId={0}" ItemStyle-Font-Underline="true"/>
<asp:BoundField DataField="AutomationType" HeaderText ="Automation Type" ItemStyle-Width="7%"/>
</Columns>
</asp:GridView>
The number of cells in GridView2 are probably less than the cell you are trying to access. I think the number of cells (columns) are 13 and you have to use index,12 instead of 13. Its better to check the number of cells before accessing one of those.
if (e.Row.Cells.Count > 12 && e.Row.Cells[8].Text.Equals("0"))
{
e.Row.Cells[12].Text = "0%";
return;
}
Edit based on OP comments
You are trying to access the value that is not yet being assigned in RowDataBound event. In this event you can access the data item and parse it instead of parsing the control/cells.
Change
Int32.TryParse(item.Cells[8].Text, out p);
To
p = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "ColumnFromDatabase"));
Note: Same goes for other columns values.
hey I'm using to buttons in a gridview each which I want to assign to specific action involves retrieving certain cell values from the gridview columns
I tried using
GridViewRow row = (GridViewRow (((Button)e.CommandSource).NamingContainer);
but it gives me Unable to cast object of type 'System.Web.UI.WebControls.GridView' to type 'System.Web.UI.WebControls.Button'.
I also tried
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = GridView1.Rows[index];
it gives me the following error
Specified argument was out of the range of valid values.
Parameter name: index
note that when I tried to specify the commandParameters property of the ButtonField the compiler said that it's not a valid parameter for the ButtomField
and I have 8 columns in the gridview so its not out of range
or alternatively could I use more than one select command button
if so how to say which one is clicked??
please help me im desperate
ASP code:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="AcitivityId" DataSourceID="SqlDataSource1" Height="304px" Width="912px" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundField DataField="AcitivityId" HeaderText="AcitivityId" InsertVisible="False" ReadOnly="True" SortExpression="AcitivityId" />
<asp:BoundField DataField="ActiviityName" HeaderText="ActiviityName" SortExpression="ActiviityName" />
<asp:BoundField DataField="ActivityLocation" HeaderText="ActivityLocation" SortExpression="ActivityLocation" />
<asp:BoundField DataField="ActivityStartDate" HeaderText="ActivityStartDate" SortExpression="ActivityStartDate" />
<asp:BoundField DataField="ActivityDueDate" HeaderText="ActivityDueDate" SortExpression="ActivityDueDate" />
<asp:BoundField DataField="ActivityDescription" HeaderText="ActivityDescription" SortExpression="ActivityDescription" />
<asp:ButtonField ButtonType="Button" CommandName="Avaliable" Text="Show avaliable buses" />
<asp:ButtonField ButtonType="Button" CommandName="Assigned" Text="Show assigned buses "/>
</Columns>
</asp:GridView>
I use this code in a number of places on my site to get the row from an object triggering a GridViewRowCommand
protected void btnUpdate_Command(object sender, CommandEventArgs e)
{
GridViewRow g = (GridViewRow)((Button)sender).NamingContainer;
// other stuff
}
Hope this helps.
In reference to Link loaded into my gridview try to navigate to my local server. The columns I have in the datagrid are Customer #, Description, Link.
I've got a function set up that's called on rowDataBound, but how do I retrieve what link is in the row so that I can edit it, and then rebind it to the datagrid?
protected void grdLinks_RowDataBound( object sender, GridViewRowEventArgs e )
{
if ( e.Row.RowIndex == 2 )
{
}
}
And here is my gridview code
<asp:GridView ID="grdLinks" runat="server" AutoGenerateColumns="False" DataSourceID="ldsCustomerLinks"
OnRowDataBound="grdLinks_RowDataBound" EmptyDataText="No data was returned."
DataKeyNames="ID" OnRowDeleted="grdLinks_RowDeleted" Width="80%" BackColor="White"
HorizontalAlign="Center" BorderColor="#999999" BorderStyle="None" BorderWidth="1px"
CellPadding="3" GridLines="Vertical">
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="CustomerNumber" HeaderText="Customer Number" SortExpression="CustomerNumber" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:HyperLinkField DataTextField="Link" HeaderText="Link" SortExpression="Link" DataNavigateUrlFields="Link" Target="_blank" />
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="ldsCustomerLinks" runat="server" ContextTypeName="ComplianceDataContext"
TableName="CustomerLinks" EnableDelete="true">
</asp:LinqDataSource>
If I'm understanding you correctly, you want to get the value of a data item called Link. If so, then something like this should work:
EDIT: I think what you're saying is that you want to grab the value Link from the database, manipulate it and then set the Url of the HyperLink to the new, manipulated value, if so then it would look like this:
ASPX Page (Updated to reflect posted code)
<Columns>
<asp:BoundField DataField="CustomerNumber" HeaderText="Customer Number" SortExpression="CustomerNumber" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:TemplateField HeaderText="Link">
<ItemTemplate>
<asp:HyperLink ID="hlParent" runat="server" Text='<% #(Eval("Link")) %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
I modified the ASP from your original question by adding an ID and removing the reference to the NavigateUrl attribute from the HyperLink control.
Code
protected void grdLinks_RowDataBound( object sender, GridViewRowEventArgs e )
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string link = DataBinder.Eval(e.Row.DataItem, "Link") as string;
if (link != null && link.Length > 0)
{
// "FindControl" borrowed directly from DOK
HyperLink hlParent = (HyperLink)e.Row.FindControl("hlParent");
if (hlParent != null)
{
// Do some manipulation of the link value
string newLink = "https://" + link
// Set the Url of the HyperLink
hlParent.NavigateUrl = newLink;
}
}
}
}
RowDataBound is called for every row in the GridView, including headers, footers, etc. Therefore, you should start by examining only the rows containing data.
Once you're on a row, there are several ways to examine the cells. One is just to use the cell index (2 here). That seems simple in your situation, but will lead to frustration if you ever rearrange the columns.
Here's an example of that from MSDN:
void CustomersGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
// Display the company name in italics.
e.Row.Cells[1].Text = "<i>" + e.Row.Cells[1].Text + "</i>";
}
A better way is to use FindControl with the item's ID.
protected void gvBarcode_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink hlParent = (HyperLink)e.Row.FindControl("hlParent");
}
}
You may also want to look into letting the gridview do it for you.
You can use the datanavigateurlformatstring property to insert querystring parameters if that's what you are trying to do.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hyperlinkfield.datanavigateurlformatstring.aspx