Change URL of Hyperlink in ASP.net gridview itemTemplate dynamically - c#

I am creating a UI that contains an itemTemplate w/in a gridView. inside the ItemTemplate I need a link that will be populated dynamically based on the table values I am binding to the table. In other words, sometimes the link will point to a file on my server, and sometimes it will point to another URL. In essence, I need to be able to check a flag on the table I'm binding to the gridview, and then update each rows itemTemplate based on data in the table for the corresponding row.
So far, I have this markup:
<asp:GridView ID="grdVDocuments"
runat="server"
DataSourceID="sqlDS_wwso"
EnableModelValidation="True"
AutoGenerateColumns="False"
OnRowDataBound="grdVDocuments_RowDataBound"
CssClass="documents_DataTable" AllowPaging="True"
>
<Columns>
<asp:TemplateField HeaderText="Download">
<ItemTemplate>
<a href="/<%# Eval("fileName") %>" target="_blank" id="lnkContent">
<img src="images/orange_download_cropped.png" alt="" border="0"/></a>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="displayName" HeaderText="displayName" SortExpression="displayName" />
<asp:BoundField DataField="fileName" HeaderText="fileName" SortExpression="fileName" />
<asp:BoundField DataField="category" HeaderText="category" SortExpression="category" />
<asp:BoundField DataField="sub_category" HeaderText="Sub-Category" SortExpression="sub_category" />
<asp:BoundField DataField="datePosted" HeaderText="datePosted" SortExpression="datePosted" />
</Columns>
</asp:GridView>
and this code-behind, which is bombing because it can't identify the hyperlink
protected void grdVDocuments_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink myHyperLink = e.Row.FindControl("lnkContent") as HyperLink;
myHyperLink.NavigateUrl = "<someOtherURL>";
}
}
The data table has a flag on called isFile which is "bit" dataType. When isFile=1 the URL needs to be ".../", otherwise the URL in the hyperlink of the itemtemplate for each row needs to be set to another field in my table that holds a URL; i.e. "someOtherURL".
Any help is appreciated ;)
Thanks!

You need to use a server control inside the ItemTemplate. So, you need to add runat="server" attribute to the a tag. But then, it is an HtmlAnchor element, and you need to cast as HtmlAnchor instead of Hyperlink like (code-behind):
...
var myHyperLink = e.Row.FindControl("lnkContent") as HtmlAnchor;
myHyperLink.HRef = "<someOtherURL>";
...
Or, you can use <asp:Hyperlink> tag in you aspx markup (instead of html anchor a)

Related

Asp.Net WebForms Gridview OnRowCommand Event not hitting code behind method

I am trying to incorporate an edit button in a grid view.
However the on row command does not seem to be firing.
I put a break point on the onrowcommand method i have implemented in the code behind.
Here is the View (i substituted the imageurl with xxx's as privacy concern on here):
<asp:GridView ID="GridViewContacts1" runat="server" CssClass="data_table" AutoGenerateColumns="false" OnRowCommand="GridViewContacts1_OnRowCommand" EmptyDataText="There are no contacts for this prospect." >
<AlternatingRowStyle CssClass="alternating_row" />
<Columns>
<asp:BoundField DataField="ContactName" HeaderText="Name" />
<asp:BoundField DataField="ContactTitle" HeaderText="Title" />
<asp:TemplateField HeaderText="Phone" SortExpression="PhoneNumber">
<ItemTemplate>
<%# FormatPhone(Eval("PhoneNumber").ToString()) %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email"></asp:BoundField>
<asp:TemplateField HeaderText="Edit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="icmdEditContact" Runat="server" ImageUrl="xxxxx" BorderStyle="None" CommandName="EditContact" CommandArgument='<%# Eval("ContactId") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton CommandArgument='<%# Eval("ContactId") %>' CausesValidation="false" CommandName="DeleteItem" OnClientClick="javascript:return confirm('Are you sure you want to delete this record?')" Runat="server" ID="Linkbutton1"><img src="xxxxx" border="0"/></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
As you will see the OnRowCommand Property of the grid view is : GridViewContacts1_OnRowCommand
Here is the code behind
The problem i'm having is this isn't getting hit :
Any ideas or suggestions ?
I even tried to incorporate without the rowcommand by just using a normal button and click event and it still wouldn't hit the designated codebehind method for that click event.
Do both buttons not work, or just the delete button?
Make sure viewstate is not turned off for the GV, and "always" give each button a "id" - your delete button is missing one.
On the other hand?
I often, and in fact BEYOND often just dump the built in commands for the GV. You actually don't need them.
For any button, image button etc that you drop into your GV (templated column), then you can just add/use/have a plain jane click event, and then use that.
The "bonus" then is you are free to add new buttons, and you don't have to use nor mumble jumpble all of the commands into that one on-row command routine anyway.
So, do check:
make sure view state of gv not turned off
make sure each button has a "id"
make sure you not re-binding the gv on page load each time
(you look to have the all important !IsPostback (good).
However, as noted, I don't use the row commands anymore.
You can do it this way:
Say this GV.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" width="40%" CssClass="table table-hover" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server"
Checked='<%# Eval("Active") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="View" CssClass="btn"
OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code to load:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL =
#"SELECT * FROM tblHotelsA ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
And we see/get this:
Button click code - each button is SEPERATED - nice!!
So, this code:
protected void cmdView_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
GridViewRow gRow = (GridViewRow)btn.NamingContainer;
int iPK = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
Debug.Print("Database PK = " + iPK);
Debug.Print("Row index click = " + gRow.RowIndex);
Debug.Print("Hotel Name = " + gRow.Cells[3].Text); // non template values
// get value of check box control on this row
CheckBox chkActive = (CheckBox)gRow.FindControl("chkActive");
Debug.Print("Value of active check box control = " + chkActive.Checked);
// hide gv, show edit area.
// bla bla bal
}
Now clicking on a button, we get this output:
Database PK = 16
Row index click = 0
Hotel Name = Batman's Cave
Value of active check box control = True
So,
Note how we use database "datakeys" option. This is VERY improant for secuirty, since the database row PK is NEVER exposted client side.
However, as above shows:
You can easy get the datakeys (row PK id)
You can easy get the row index
you have full use of the row (namingcontainer)
you can use find control etc.
So, really, I see LITTLE reason to use the built in row index command.
You ARE free to add/use/have/enjoy the command arugument for a button, or image button, or link buttion and I'll often use that to add/supply extra information to pass to the button).
But for the public and history?
Check viewestate, add "id" to those buttons that don't have one.
However, all in all, since you can just use/add/have a button click like any other button you drop into a page, then I just continue to use simple plain jane button clicks, and not bother with the GV event model.
Note that naming container trick used above works for repeaters/listview/datalist etc.

Problem with being able to access certain elements in GridView -> TemplateField -> EditItemTemplate

I have this problem with being able to access certain elements in
GridView -> TemplateField -> EditItemTemplate.
To be more clear, I have textbox and button
(in GridView -> TemplateField -> EditItemTemplate) and only one of them must be visible depending on operation. If I want to edit, button must be visible and if I want to add new user then textbox must be visible. I have added my aspx code for you to check and also C# code-behind. The method in C# code is the one which gets called immidiately when I press "Edit" button which lets to edit account details and permissions for one user. And I want that this method would decide whenever to show textbox or button (I have IsUserInsertMode property for that.)
I would be really grateful for someone who would help me out with this.
<asp:GridView CssClass="grid" ID="gridUsers" runat="server"
AutoGenerateColumns="False" DataKeyNames="id"
DataSourceID="dsrcUserList" GridLines="None"
OnRowCommand="gridUsers_RowCommand" OnDataBound="gridUsers_DataBound"
OnRowUpdating="gridUsers_Updating" OnRowUpdated="gridUsers_Updated" EnableModelValidation="True">
<Columns>
<asp:TemplateField HeaderText="Password" ItemStyle-HorizontalAlign="center" ItemStyle-Width="80px">
<ItemTemplate>
*******
</ItemTemplate>
<EditItemTemplate>
**NEED REFERENCES TO THESE TWO ITEMS IN ORDER TO SET THEIR VISIBILITY**
<asp:Button ID="btnEditPassword" Text="Change" runat="server" CausesValidation="false" OnClick="btnEditPassword_Click" Visible="false"/>
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Text='<%# Bind("Password") %>' Width="74px" MaxLength="50" Visible="true" />
</EditItemTemplate>
</asp:TemplateField>
**LOTS OF CHECKBOXES LIKE THOSE**
<asp:CheckBoxField DataField="AccessTowsRelease" HeaderText="TowsRelease" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessTowsView" HeaderText="TowsView" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessSMS" HeaderText="SMS"
ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
**MY EDIT BUTTON**
<asp:CommandField ButtonType="Link"
ShowEditButton="true" EditText="Edit"
CancelText="Cancel" UpdateText="Save" />
</Columns>
</asp:GridView>
C# code-behind (I have added some of the stuff that I have tried)
// this is called when I press some button which lets me to edit one user data including password
// but when I want to change password, there should be button which would redirect to different
// window to do the password change procedure.
// And when I want to add new user there should be textbox for password, not the button.
protected void gridUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
//Found the way to get the index of current row (represents one row of information which is visible for the client in browser)
int rowIndex = Convert.ToInt32(e.CommandArgument);
//if those would be working I wouldn't be here asking for help
btnEditPassword.Visible = true;
txtPassword.Visible = false;
//Can't cast 'System.Web.UI.WebControls.GridView' to type 'System.Web.UI.WebControls.GridViewRow'
Button btnEditPassword = (Button)((GridViewRow)sender).FindControl("btnEditPassword");
//every attempt to use FindControl gets me null
Button btnEditPassword = (Button)this.gridUsers.Rows[rowIndex].FindControl("btnEditPassword");
// my way to check if it works - if its null then I do can't anything (prints to browser console).
if (btnEditPassword != null) Response.Write("<script>console.log('not null')</script>");
else Response.Write("<script>console.log('null')</script>");
}
The RowCommand-event is raised too early for your case. It's raised before the row is going into edit mode, that's why you don't find the controls of your edit-item-template.
First change your markup to handle the RowDataBound-event:
<asp:GridView ... OnRowDataBound="gridUsers_OnRowDataBound" ...>
Then handle this in the OnRowDataBound-event like this:
protected void gridUsers_OnRowDataBound(object sender, GridViewRowEventArgs e) {
// check if row is in edit state
if ((e.Row.RowState == DataControlRowState.Edit) || (e.Row.RowState == (DataControlRowState.Alternate | DataControlRowState.Edit))) {
// look for the control in the row
Button btnEditPassword = (Button)e.Row.FindControl("btnEditPassword");
}
}

Change AutoGeneratedDelete LinkButton of Gridview to an Image Button

i have a gridview with AutoGenerateDeleteButton Property set true.
Of course this property auto generates a linkbutton at the leftmost of the gridview, my question is, how can i change it to an Image Button?? i wanted my gridview to look more presentable by making the control buttons an image.
Thanks! :)
You can do by using template in grid...
for more info
http://p2p.wrox.com/asp-net-2-0-professional/46216-image-button-template-field-gridview-control.html
You can create a TemplateField and use autogeneratecolumns="false".
Here's an example of a GridView:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns ="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="Link" runat="server" Text="click" OnClick="link_Click"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="field1" HeaderText="My Column 1" />
<asp:BoundField DataField="field2" HeaderText="My Column 2" />
</Columns>
</asp:GridView>
Where field1 and field2 are headers from your DataTable
And to access the row within the event handler:
protected void link_Click(object sender, EventArgs e)
{
int rowindex = ((GridViewRow)((Control)sender).NamingContainer).RowIndex;
//do something with rowindex etc
}
Add new Template Column and in add image button and set CommandName='Delete' it'll raise the delete event automatically.
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgDelete" ImageUrl="~/imgs/Delete.png"
CommandName="Delete" runat="server" />
</ItemTemplate>
</asp:TemplateField>
Try this
<Columns>
<asp:CommandField ButtonType="Image" DeleteImageUrl="~/Images/DeleteImage.png"
ShowDeleteButton="true"/>
</Columns>
And set AutoGenerateDeleteButton="false"
Or Refer this too

GridView Checkbox - Cannot Change Properties

I have an ASP GridView with a column that contains CheckBox controls. These CheckBoxes are bound to a bit field accessed via a SqlDataSource. The GridView is editable and the CheckBoxes are disabled on load.
I am trying to get the enabled property to change to true during edit, so the CheckBox in the row that is being edited can be changed, and this change updated to the bit field in the database.
The ASP code
<asp:UpdatePanel ID="upGridView" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="gvChecklist" runat="server"
AutoGenerateColumns="false" DataSourceID="dsChecklist"
AutoGenerateEditButton="true" onrowupdating="gvChecklist_RowUpdating"
onrowediting="gvChecklist_RowEditing">
<Columns>
<asp:TemplateField HeaderText="Finished">
<ItemTemplate><asp:CheckBox ID="cbFinished" runat="server" Enabled="false" Checked='<%# Eval("Finished") ?? false %>' /> </ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Division"
HeaderText="Division"
readonly="true" />
<asp:BoundField DataField="Application"
HeaderText="Application"
readonly="true" />
<asp:BoundField DataField="Task"
HeaderText="Task"
readonly="true" />
<asp:BoundField DataField="TestedBy" HeaderText="Tested By" readonly="true"/>
<asp:BoundField DataField="Notes" HeaderText="Notes" ReadOnly="false"/>
<asp:BoundField DataField="JiraTicket"
HeaderText="JIRA Ticket"
readonly="false" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
C# Code Behind for the RowEditing event
protected void gvChecklist_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView gvChecklist = (GridView)LoginView1.FindControl("gvChecklist");
CheckBox cb = (CheckBox)gvChecklist.Rows[e.NewEditIndex].Cells[1].FindControl("cbFinished");
cb.Enabled = true;
gvChecklist.DataBind();
}
-edit: I felt the need to add a little more information here. The code to set the CheckBox cb to the GridView Row's CheckBox seems to be working correctly, as I can see the enabled property = true through the debugger. I am wondering if it is getting set back to false due to PostBack after this event runs. The Load method for this page is empty, but I am thinking that the enabled=false code is being hit in the ASP page.
UI of GridView
The solution for this was surprisingly simple. Instead of putting a CheckBox in a TemplateField, I was able to set a DataField property for the CheckBox column. This allowed the edit functionality to work with no further C# code.
<asp:CheckBoxField DataField="Finished"
HeaderText="Finished"
readonly="false" />

how to find out the selected row in a gridview

I am doing a project in .net with c#. in that there is a registration form of new users into the site. admin should approve the registration. for that I'm using a GridView. How to find out the selected row in the grid view?
Use the GridView.SelectedRow property.
Alternatively, you can get the index of the selected row with the GridView.SelectedIndex property.
are you perhaps referring to a DATAGRIDVIEW?
if so, to find the content of a certain column of the selected row
datagridviewname.item(0, datagridviewname.currentrow.index).value
where 0 = first column of your datagrid
Use following gridview property>
gvTradeFile.SelectedRows[0].Cells[10].Value.ToString();
Hope this will help you.
Normally I use RowCommand for this type of thing:
<asp:GridView runat="server" id="gvUsers" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="username" HeaderText="Username" />
<asp:BoundField DataField="dateregistered" HeaderText="Date" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkApprove" CommandName="Approve" CommandArgument='<%# Eval("userid") %>' Text="Approve"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkDeny" CommandName="Deny" CommandArgument='<%# Eval("userid") %>' Text="Deny"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now you need to pass instructions through on RowCommand...
private void gvUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "Approve":
// Executes code to update the users table,
// setting the approved flag to true
// Usage: ApproveUser(integer userid);
ApproveUser(e.CommandArgument);
break;
case else:
// do whatever if the user registration wasn't approved
break;
}
}
The switch is a good idea in case you need to do a few things with the data here. It evaluates the primary key value for the row (in this case, that's the value of the userid column in the database) for the selected row (automatically determined when you click the link) along with the CommandName to tell it what to do with that information.
Hope this helps.

Categories

Resources