Adding link dynamically to Template Field - asp.net

I need to replace the link for each data bound item. I already checked out the databound event of the datarow. The problem with that is I can't control where the link shows up. I'm trying to stay away from javascript and keep it mostly in the code behind. Below is my asp code and the code behind I have. I also want to try to keep as much the same as possible, not changing to the html template items. The process Im using is as follows.
I have a custom object which contains all the fields and data of a blog entry. Those items are put into a list and then supplied to the datagrid.
<asp:GridView ID="grdRecentNews" runat="server" AutoGenerateColumns="False" DataKeyNames="Key"
GridLines="None" PageSize="4" ShowHeader="False"
AllowPaging="True">
<PagerSettings Visible="False" />
<Columns>
<asp:TemplateField>
<ItemTemplate>
<blockquote>
<%-- <strong><a href=**"News.aspx"**>--%>
<strong><a href="News.aspx">
<%#Eval("NewsDesc")%></a></strong>
<br />
<span class="italic">
<%#Eval("NewsDate")%></span>
</blockquote>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
This is the code I had in the Databound event, problem being I only want to provide a link for one of the fields of the Rss object. as above below. I want to replace News.aspx" for each item added to the datagrid with the rssobject's link property.
Protected Sub grdRecentNews_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles grdRecentNews.RowDataBound
If e.Row.DataItem IsNot Nothing AndAlso e.Row.DataItem.ToString = "RssEntry" Then
Dim curItem As RssEntry = CType(e.Row.DataItem, RssEntry)
e.Row.Attributes.Add("href", curItem.Link) 'data-url
End If
End Sub

I found a way to insert an <%#Eval %> statement into the attribute I wanted to change. I point it towards the correct property of the rssobject, and its working.
<Columns>
<asp:TemplateField>
<ItemTemplate>
<blockquote>
<strong><a href='<%#Eval("Link")%>'>
<%#Eval("NewsDesc")%></a></strong>
<br />
<span class="italic">
<%#Eval("NewsDate")%></span>
</blockquote>
</ItemTemplate>
</asp:TemplateField>
</Columns>

Related

Filter gridview with OnChecked Event

I have a gridview loaded from a database with a checkbox in the first column. What I want is that when clicking on any row the grid will be filtered to show only the rows in which the value of the second cell is the same as the one I clicked on (having the option to select more rows with that value). Removing the checks he would reload all the information again. I tried doing it using the OnChecked event, but due to AutoPostBack it filters but loses the value of the checkbox checked. What is the best way to do what I want? I hope I have been explicit. Thank you
asp:GridView ID="gridview" runat="server" AutoGenerateColumns="false" DataKeyNames="Id">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkRow" OnCheckedChanged="chkRow_CheckedChanged" AutoPostBack="true" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Document" ItemStyle-Width="10%" HeaderText="Documento" />
<asp:BoundField DataField="Entidad" ItemStyle-Width="55%" HeaderText="Entidad" />
</Columns>
For Each row As GridViewRow In gvEncomendasPendentes.Rows
If row.RowType = DataControlRowType.DataRow Then
Dim chkRow As CheckBox = TryCast(row.Cells(0).FindControl("chkRow"), CheckBox)
If chkRow.Checked Then
'Bind with filter
End If
End If
Next
Does the table display the entire dataset at all times? If so, I'd check into client-side filtering (JavaScript). Not having the round trip to the server/database would make your page a lot more responsive.
But assuming that's not the case, and to actually answer the posted question, here's how I'd approach it in the VB.Net Code. Try changing the Change Event like this:
Protected Sub chkRow_CheckedChanged (sender as object, e As EventArgs)
Dim chk As CheckBox = DirectCast(sender, CheckBox)
dim grv As GridRowView = DirectCast(chk.NamingContainer, GridRowView)
dim hdn AS HiddenField = grv.FindControl("hdnFieldWithValue")
If chk.Checked then
AddValueToFilerList(hdn.Value)
Else
RemoveValueFromFilterList(hdn.Value)
End If
BindGridView()
End Sub
Your way does work, but that has a Log(N) time on processing, as it needs to look at every row in the grid. The above way will KNOW which checkbox was checked, and deal with it appropriately.
And this small change to the markup:
<asp:hiddenField runat='server' id='hdnFilterList' />
<asp:GridView ID="gridview" runat="server" AutoGenerateColumns="false" DataKeyNames="Id">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkRow" OnCheckedChanged="chkRow_CheckedChanged" AutoPostBack="true" runat="server" checked='<%# CheckValueInFilterList(Eval("Entidad")) %>' />
<asp:hiddenField id="hdnFieldWithValue" runat="server" value='<%# Eval("Entidad")' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Document" ItemStyle-Width="10%" HeaderText="Documento" />
<asp:BoundField DataField="Entidad" ItemStyle-Width="55%" HeaderText="Entidad" />
</Columns>
You'll also a function something like this:
Protected Function CheckValueInFilterList(input as string) as boolean
Return MyListOfFilterItems.Contains(input)
End Function
The purpose of that would be to see if the input is contained in your list of filters you're applying to your query and returning true/false depending on that.
Which is directly related to why you're not retaining a check in the checkboxes between postbacks. Since you're rebinding the grid, the existing form state is thrown away in favor of the values from the bind. Since your markup lacked a setter for the checkbox's checked state in the databind, it always resorted to false.
I also added a hidden field to the Markup which would contain the filter list as some type of serialized string (JSON, XML, etc). I'd read it from that field on the Page Load where IsPostBack is True, and always write the list to it in the PreRender event. The point is to just have that passed back and forth through the posted form state so that you can remember them between postbacks.
Maintaining that list of filters in a control outside of the gridview as described does add a bit of overhead in the data that is sent to/from the server on roundtrips. But I wouldn't expect that to a large amount, and would expect a preformance increase due to not having to iterate through the entire gridview item list on every postback.

How do I access a hyperlink control that's in a gridview from _RowEditing Sub?

I've run into a wall and could use some advice. I have a gridview that contains a "Details" hyperlink on each row. While I am in edit mode (inline), I want to disable the details link. I thought this would be simple, but I can't seem to make it work. I had assumed (wrongly) that I could do something like:
Dim lnkDetails As HyperLink = CType(e.Row.FindControl("lnkDetails"), HyperLink)
lnkDetails.Enabled = False
The problem here, as I found out, is the "e As GridViewEditEventArgs" part of my Sub doesn't include "Row".
Here is the relevant code:
Protected Sub gvCurRecords_RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
' Make the GridView control into edit mode for the selected row.
gvCurRecords.EditIndex = e.NewEditIndex
' Rebind the GridView control to show data in edit mode.
BindGridView()
' Hide the Add button.
lbtnAdd.Visible = False
End Sub
HTML (Only the relevant column):
<asp:GridView ID="gvCurRecords" CellPadding="4" DataSourceId="SqlDataSource1"
Autogeneratecolumns="false" AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true" OnRowEditing="gvCurRecords_RowEditing"
OnRowCancelingEdit="gvCurRecords_RowCancelingEdit"
OnRowUpdating="gvCurRecords_RowUpdating" DataKeyNames="eventID"
OnRowDataBound="gvCurRecords_RowDataBound"
OnPageIndexChanging="gvCurRecords_PageIndexChanging" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="lnkDetails" runat="server" Text='Details' NavigateUrl='<%#FormatUrl(CInt(Eval("EventID")))%>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:Gridview>
Any help would be greatly appreciated. Thanks.
Use the edit template to define a label instead of a hyperlink:
<EditItemTemplate>
<asp:Label ID="lbDetails" runat="server" Text='something else' />
</EditItemTemplate>

Gridview is not updating inside of UpdatePanel

I understand that this is a very common issue, I have been reading documentation on it for days, and I am about to pull my hair out over this issue.
BACKGROUND
I have multiple Gridviews inside of an UpdatePanel. What is happening, is someone is importing an Excel spreadsheet, I am using OpenXML to shread the data and store it in a VB.NET datatable object. I then run all of that data through a custom validation (based on DB information) and then spit out the exceptions (errors) that occur into a Gridview depending on the exception. the max number is 4 Gridviews in one UpdatePanel (each Gridview has it's own functionality). There are two Gridviews that I am using a button to do an action using the data contained in the Gridview. Those two buttons are also located in the Update Panel, just underneath the corresponding Gridviews. Each Gridview is wrapped in an AJAX Collapsible Panel Extender.
Now, when the user clicks on the button, I have a click event in the code behind where I take the information and depending on the exception that occurred, Update or Insert the DB. I loop through the rows, and if no error occurs, I call the datatable.ImportRow and pass the current row to my "Ready" table. I use a ScriptManager.RegisterStartupScript in order to display an alert box letting them know if any errors occurred. Then, I rebind the exception table and the "Ready" table. I have tried just adding an AsyncPostbackTrigger, I have attempted simply calling udpMain.Update() in the code behind, and tried both options of setting the UpdatePanel's UpdateMode property to "Always" and "Conditional".
HTML
<asp:UpdatePanel ID="udpMain" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Panel ID="pnlOwnershipDetailsHead" runat="server" Visible="false">
<div class="windHeader" style="cursor: pointer">
<asp:Label id="lblOwnershipDetails" runat="server">Ownership Exceptions</asp:Label>
<asp:ImageButton id="btnOwnershipHead" runat="server"/>
</div>
</asp:Panel>
<asp:Panel ID="pnlOwnershipDetailsBody" runat="server" Visible="false" CssClass="pnl">
<asp:GridView ID="gvOwnershipDetails" runat="server" CssClass="wind" CellPadding="5" AutoGenerateColumns="false">
<HeaderStyle CssClass="windHeader" />
<Columns>
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Serial Number" HeaderText="Serial Number" />
<asp:BoundField DataField="Facility" HeaderText="Facility" />
<asp:BoundField DataField="Department" HeaderText="Department" />
<asp:BoundField DataField="EmpID" HeaderText="EmpID" />
<asp:BoundField DataField="Configuration" HeaderText="Config" />
<asp:BoundField DataField="Error" HeaderText="Errors" />
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkHeader" ToolTip="Select All" runat="server" onclick="changeAllCheckBoxes(this)" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkItem" runat="server" ToolTip="Select this item" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="btnOwnershipDetails" Text="Change Information" runat="server" CssClass="btn editBtn" />
<ajax:ConfirmButtonExtender ID="cbeOwnershipDetails" runat="server" TargetControlID="btnOwnershipDetails"
ConfirmText="Are you sure you would like to change the ownership information for the selected items?"
OnClientCancel="CancelClick" />
</asp:Panel>
</ContentTemplate>
<asp:UpdatePanel>
CODE BEHIND
Protected Sub btnOwnershipDetails_Click(sender As Object, e As System.EventArgs) Handles btnOwnershipDetails.Click
Dim importdata As New ImportData
Dim ownershipdt As Data.DataTable = Session("ownershipdt")
Dim finalimportdt As Data.DataTable = Session("finalimportdt")
Dim existsError As Boolean = False
For Each Row As Data.DataRow In ownershipdt.Rows
Dim i As Integer = 0
Dim cb As CheckBox = CType(gvOwnershipDetails.Rows(i).Cells(7).Controls(1), CheckBox)
If cb.Checked Then
If importdata.CheckEmpExists(Row("EmpID").ToString) And importdata.CheckSiteExists(Row("Facility").ToString) And importdata.CheckDeptExists(Row("Department").ToString) Then
importdata.UpdateDBOwnership(Row("Serial Number").ToString, ClientInfo.GetEmpID(Row("EmpID").ToString), ClientInfo.GetSiteID(Row("Facility").ToString), ClientInfo.GetDeptID(Row("Department").ToString), _
Row("Description").ToString, Row("Configuration").ToString, portalUser.EmployeeText)
finalimportdt.ImportRow(Row)
Else
existsError = True
End If
End If
i += 1
Next
If existsError = False Then 'Show alert box
ScriptManager.RegisterStartupScript(udpMain, udpMain.GetType(), "alert", "alert('You have changed the ownership information for the selected rows.')", True)
Else
ScriptManager.RegisterStartupScript(udpMain, udpMain.GetType(), "alert", "alert('There was an issue changing ownership to all of the selected rows.')", True)
End If
bindGV(gvOwnershipDetails, ownershipdt)
bindGV(gvImportDetails, finalimportdt)
'udpMain.Update()
Session("ownershipdt") = ownershipdt
Session("finalimportdt") = finalimportdt
btnEmail.Enabled = True
End Sub
Put your panel code between ContentTemplate under asp:UpdatePanel
<asp:UpdatePanel>
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
Finally! I Have found the answer! https://sites.google.com/site/arlen4mysite/full-postback-for-templatef
Or a single line of code in the Page_Load() does the same thing
ScriptManager.GetCurrent(this).RegisterPostBackControl(btnOwnershipDetails);

asp.net VB gridview checkbox always show false on serverside code behind

I am trying to implement a gridview with checkbox column on asp.net (VB). when the user checks checkbox and click delete button, it should access database and delete all checked item.
I have already tried numerous googled solution and never worked for me. here is short scenario
on my aspx page:
1)search by id text box, when user enter ID and click search button, the below table is displayed
<asp:GridView ID="MyGridView" runat="server">
<Columns>
<asp:TemplateField headertext="Name">
<ItemTemplate>
<asp:Label id="namelbl"
text='<%# Eval("name")%>' runat="server"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete Now?">
<ItemTemplate>
<asp:CheckBox Enabled="true" ID="chkStatus" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
after data is displayed, user checks the desired checkbox and click delete button, then the code behind is run
Protected Sub DelSelected(ByVal sender As Object, ByVal e As System.EventArgs)
Dim idList as ArrayList = new ArrayList()
For Each row As GridViewRow In MyGridView.Rows
Dim selectcb As CheckBox = CType(row.FindControl("chkStatus"), CheckBox)
If (selectcb.Checked) Then
'put into delete list
Trouble starts here, selectcb checkbox is always false
How could that happen, any idea would be appreciated
Thanks
you must bind your data only when no IsPostback in order to persist your checkbox selected, and no reset
If(! IsPostBack)
{
Bind();
}

Dropdownlist results in gridview

I'm having some trouble getting the results of the drop-downs in a gridview, and haven't found any helpful articles for VB code.
What I'm trying to do is build a site for tests. So far I have the gridview built w/the extra column for a drop-down list where the true/false answer will be selected. When the test is completed, there is a submit button. All is well except I need to be able to get the results of each drop-down list on post-back to a variable or array (each test contains 10 questions) so the results can be checked/graded. When the results are determined I would like to display a label in it's place and change the text value accordingly (correct or incorrect), so I'll need to be able to enumerate these as well (i.e. label1.text="Correct!", label2.text="Incorrect!", etc...).
Code so far.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" BackColor="White" BorderColor="#3366CC"
BorderStyle="None" BorderWidth="1px" CellPadding="1">
<RowStyle BackColor="White" ForeColor="#003399" />
<Columns>
<asp:BoundField DataField="Question" HeaderText="Question"
SortExpression="Question" />
<asp:TemplateField HeaderText="Answer">
<ItemTemplate>
<% If Not IsPostBack Then%>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlAnswer"
DataTextField="torf" DataValueField="torf">
</asp:DropDownList>
<%Else%>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<%End If%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
<PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" />
<SelectedRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
<HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" />
</asp:GridView>
The preceding code loads 10 rows, 2 columns (column1:Question | column2-[DropDownLists]:Answer). I'm a freshman when it comes to development, so if you need additional info let me know.
Here is how I handled it:
created a page level private variable to hold our list of correct/incorrect values
Private Answers as New List(Of Boolean) 'creates a strongly typed list of t/f values
in Page.Load
if IsPostBack then
'iterate through each row
for each gridRow As GridViewRow in GridView1.Rows
'get the selected value for this answer
Dim answer as string = CType(gridRow.FindControl("DropDownList1"),DropDownList).SelectedValue
'add this answer to the list
Answers.Add(IsCorrectAnswer(answer))
next
end if
the IsCorrectAnswer function determines whether or not the answer given for this question is correct and returns a Boolean value. You would need to write this function to suit your needs.
in Button1.Click handler
'rowCounter will act as an index to the answers
Dim rowCounter as Integer = 0
For Each gridRow as GridViewRow in GridView1.Rows
'grid_RowDataBound handles the binding of single row
grid_RowDataBound(gridRow, rowCounter)
rowCounter+=1
Next
finally
Private Sub grid_RowDataBound(gridRow as GridViewRow, rowCounter as Integer)
'make the dropdown invisible
CType(gridRow.FindControl("DropDownList1"),DropDownList).Visible = False
'because we'll be acting on two properties of the label, I shove it in a variable first for ease of access
Dim label As Label = CType(gridRow.FindControl("Label1"),Label)
'set the label to visible
label.Visible = True
'set the text
label.Text = Iif(Answers(rowCounter),"Correct", "Incorrect")
End Sub
Someone probably has a cleaner solution than this, but I do know this works, at least as far as I understand the issue you are facing.
Good luck
What about binding the Visible attribute to Page.IsPostBack (note this is in C# since I'm not familiar with the syntax for VB.NET... I'm sure something similar would work):
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlAnswer"
DataTextField="torf" DataValueField="torf" Visible='<%# !Page.IsPostBack %/>></asp:DropDownList>
<asp:Label ID="Label1" runat="server" Text="" Visible='<%# Page.IsPostBack %/></asp:Label>
</ItemTemplate>
check the RowDataBound event of the gridview object. It takes two parameters:
(byval sender as Object, byval e as GridViewRowEventArgs). With it, you can set the value of the label in each row to 'Correct' or 'Incorrect' on the postback.
see the example at
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowdatabound.aspx
for more information
as for getting the answers into a variable, here are a couple of options
1) check viewstate. It has some overhead, so be cautious with it.
2) save the data to a Session object

Resources