Why is my CommandArgument Empty? - asp.net

I have an ASP.Net page, which displays a list of options to the user. When they select from the list, it does a post back and queries a sql server. The results are displayed in a listview below the options in an update panel. Below is a snippet of the ItemTemplate:
<asp:LinkButton Text="Save IT" OnCommand="SaveIt" CommandArgument="<%# Container.DataItemIndex %>" runat="server" />
The DataItemIndex does not appear, so my commandargument is empty. However, the object sender is the button, which shows the item.
Why is the index item not appearing in the CommandArgument?
Could it be the post back? If so, why would it be the post back? Is there a way around it?
Edit:
Sorry, from my attempts to solve it before, I posted bad code, but it still isn't appearing.
Resolution:
I found another work around in that the sender of the OnCommand is the link button, which has the CommandArgument. I will chalk this issue up to be an issue with multiple postbacks and javascript.

You can't use the <%= %> syntax inside properties on a tag with a runat="server" attribute. I'm surprised the code will even run. :)
UPDATE:
You probably want to use the ItemDataBound event on the repeater, find the linkbutton and set the CommandArgument property.
Not very elegant, but here's a VB.NET sample.
Private Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Select Case e.Item.ItemType
Case ListItemType.Item, ListItemType.AlternatingItem
Dim b As LinkButton = e.Item.FindControl("btn")
b.CommandArgument = e.Item.ItemIndex
b.DataBind()
End Select
End Sub

You're not setting it
You possibly want
<%# Container.DataItemIndex %>
or
<%= Container.DataItemIndex %>
:)

Try
<asp:LinkButton Text="Save IT" OnCommand="SaveIt" CommandArgument="<%# Container.DataItemIndex %>" runat="server" />
You were missing the "#" sign.

This site really helped me with this problem: http://forums.asp.net/t/1671316.aspx
The issue I ran into was that I was being passed null arguments in the commandargument when I clicked on the button a second time. As the post above explains, this is because commandargument is only set in the databind event. So, to fix this, include a databind event in the page_load sub
Ex. (VB)
Private Sub BindSelectButtons()
'Purpose: bind the data to the select buttons for commandargument to be used
Dim i As Integer
For i = 0 To gridview1.Rows.Count - 1
gridview1.Rows(i).Cells(8).FindControl("btnID").DataBind()
Next
End Sub
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
'Rebind select buttons so that the commandargument refreshes
BindSelectButtons()
End Sub

Make sure View State is enabled
e.Row.EnableViewState = true;

Related

When does DataBinding Occur for Drop Down Lists?

Here is my drop down list and data source. My question is.. when is it possible to set a defaulted selected option for the drop down list, aka when have all the dropdownlists been databound and their ListItems populated? I have tried Page_PreRender, Page_PreRenderComplete, Page_Load.
I have read over MSDN's Page Life cycle event which suggest Page_PreRender.
<asp:DropDownList ID="ddlRampStandard" runat="server"
DataSourceID="RampStandardDataSource" DataTextField="StandardName"
DataValueField="StandardName" RepeatDirection="Horizontal"
ViewStateMode="Enabled"></asp:DropDownList>
<asp:SqlDataSource ID="RampStandardDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:AIMP_DeleteMeConnectionString %>"
SelectCommand="SELECT [StandardName] FROM [CR_Standard]"></asp:SqlDataSource>
Here's the simple code-behind which illustrates what I'm trying to do.
Protected Sub Page_PreRenderComplete(sender As Object, e As System.EventArgs) Handles Me.Load
ddllstSideOfStreet.Items(0).Selected = True
End Sub
I'm getting an instance not created error suggesting ddllstSideOfStreet has no items. I do verify that with a breakpoint and watch that there are no items in existence in any of the previously mentioned prerender, load, prerendercomplte functions.. However when the page loads, the dropdownlist does indeed load with the expected databound information. Thoughts?
just to make sure, have both the handler in the markup and the method using the correct handler in the code behind.
Like this:
Protected Sub Page_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
End Sub
And the markup as follows:
<asp:DropDownList ID="ddlRampStandard" runat="server"
DataSourceID="RampStandardDataSource" DataTextField="StandardName"
DataValueField="StandardName" RepeatDirection="Horizontal"
ViewStateMode="Enabled" OnPreRender="Page_PreRender"></asp:DropDownList>
Tried a similar solution on my machine a moment ago and it worked.

ImageButton not firing

I have the following button:
<asp:ImageButton ID="imgbtnEditInfo" runat="server" ImageUrl="~/images/EditInformation.png" AlternateText="EditInformation" CommandName="EditDetails" CommandArgument="<%# Container.DataItemIndex %>" OnClick="lnkEdit_Click" Enabled="true" />
I have the following method but looks like it is not hitting the method:
Protected Sub lnkEdit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
End Sub
Wondering if I am missing something. I put a breakpoint on the Protected Sub lnkEdit_Click but on click of the imagebutton I do not go there.
You're working with Data Controls (GridView or DataList etc). To respond to the button/linkbutton/imagebutton events, you must have to handle the parent - data control's events.
Without seeing more of your page it is hard to say. A couple things to check:
Is the ImageButton inside a <form runat="server">?
Have you compared your page to the VB sample at ImageButton Class to see if anything might have been missed?

"Inline" function call: function is never hit

I'm trying to make a tabbed menu for the asp.net website I'm working on. One of the pre-requisite is obviously to color the current tab differently, so the user can know on which tab is currently is.
To do this, I made this method in my code-behind:
Protected Function GetCssClass(ByVal ctrl As LinkButton) As String
If ctrl.ID = currentLink Then
Return "current"
Else
Return String.Empty
End If
End Function
and I call the method like this in my aspx page:
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="/Default.aspx" CssClass="<%#GetCssClass(LinkButton1) %>" >Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="/Directory/page1.aspx" CssClass="<%#GetCssClass(LinkButton2) %>" >Page1</asp:LinkButton>
But the method is never hit... As I understand, the method should be called each time the LinkButton is drawn...
Does someone have an idea why?
Thanks in advance !
Edit: Just as a precision, all this code is in the masterpage.
Edit2: Here are the changes I made according to Quagland's suggestion.
In the aspx masterpage:
<asp:HiddenField ID="currentLink" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="/Default.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="/OtherDirectory/Page1.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page1</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl="/OtherDirectory/Page2.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page2</asp:LinkButton>
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="/OtherDirectory/Page3.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page3</asp:LinkButton>
And in the code behind:
Protected Sub LinkButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.Click, LinkButton2.Click, LinkButton3.Click, LinkButton4.Click, LinkButton5.Click, LinkButton6.Click, LinkButton7.Click, LinkButton8.Click
Dim lnk As LinkButton = CType(sender, LinkButton)
currentLink.Value = lnk.ID
End Sub
Protected Function GetCssClass(ByVal ctrl As LinkButton) As String
If ctrl.ID = currentLink.Value Then
Return "current"
Else
Return String.Empty
End If
End Function
Protected Sub LinkButton_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.PreRender, LinkButton2.PreRender, LinkButton3.PreRender, LinkButton4.PreRender, LinkButton5.PreRender, LinkButton6.PreRender, LinkButton7.PreRender, LinkButton8.PreRender
Dim lnk As LinkButton = CType(sender, LinkButton)
lnk.CssClass = GetCssClass(lnk)
End Sub
The problem is now that the click event is not always fired. On first click, nothing happens, but on second click on a tab, the click event is correctly triggered. Any clue ?
Edit3: Could it be that the value stored in the hidden field is reset each time the masterpage is reloaded (I mean, each link points to a couple masterpage + content page) ?
You need to use <%= ... %> (i.e. replace # with =).
The hash form is used with data binding, you want to just create output.
For .NET 4 prefer <%: ... %> (use a colon) to automatically do HTML encoding.
I have quickly tested a solution that might work for you. I'm just not sure where your 'currentlink' variable comes from. I have implemented it as a hidden field here.
In Masterpage.aspx:
<asp:HiddenField ID="currentLink" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server">Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server">Page1</asp:LinkButton>
In code behind:
use your original GetCssClass function add this:
Protected Sub LinkButton_PreRender(ByVal sender As Object, ByVal e As System.EventArgs)
Handles LinkButton1.PreRender, LinkButton2.PreRender
Dim lnk As LinkButton = CType(sender, LinkButton)
lnk.CssClass = GetCssClass(lnk)
End Sub
I have put it in PreRender because i was using the LinkButton click events to set the hidden field value (and Click happens after Load but before PreRender):
Protected Sub LinkButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles LinkButton1.Click, LinkButton2.Click
Dim lnk As LinkButton = CType(sender, LinkButton)
currentLink.Value = lnk.ID
End Sub
also, if there are numerous Linkbuttons, you may want to declare like:
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender">Home</asp:LinkButton>
EDIT:
Here is another solution that will work with cross page postbacks. Not much code but you'll need to put some on every page. Anyway:
Masterpage.aspx:
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="Default.aspx">Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="Page1.aspx">Page1</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl="Page2.aspx">Page2</asp:LinkButton>
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="Page3.aspx">Page3</asp:LinkButton>
Masterpage.aspx.vb:
Public Sub SetCssClass(ByVal ctrl As String)
CType(FindControl(ctrl), LinkButton).CssClass = "current"
End Sub
All content pages:
*.aspx:
add this directive to create a strongly typed reference to the masterpage
<%# MasterType VirtualPath="~/MasterPage.master" %>
*.aspx.vb:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Master.SetCssClass("LinkButton1") '' << put the name of the relevant link button here
End Sub
Set the CssClass in the code-behind. This will state your intent more clearly than calling DataBind on your linkbuttons if you use databinding syntax. Since you're doing it for multiple controls maybe stick them in a method called ApplyCssClasses.
I'm not sure why <%= %> isn't working but personally I don't like to mix code and markup, I like to keep them completely separate.
I would suggest setting the CSS class in code perhaps on the page load event.
lnkPopulate.CssClass = "current"
<%# ... %> will work if you're OK with doing LinkButton1.DataBind() in your code-behind at the appropriate time.

Accessing data associated with the RepeaterItem on Command execution

I want to access the data associated with the RepeaterItem in which an ItemCommand fired up. The scenario is, I have multiple RepeaterItems which Button controls in which the Command is set declaratively like this:
<asp:Repeater ID="Repeater3"
runat="server"
DataSource='<%# ClientManager.GetClientEmployees(Eval("ClientID")) %>'
OnItemCommand="RemoveEmployeeFromClient">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1"
runat="server"
Text="(x)"
CommandName="RemoveEmployeeFromClient">
</asp:LinkButton>
</ItemTemplate>
<SeparatorTemplate>,<br /></SeparatorTemplate>
</asp:Repeater>
The code behind is:
Protected Sub RemoveEmployeeFromClient(ByVal source As Object,
ByVal e As RepeaterCommandEventArgs)
' I want to access the data associated with
' the RepeaterItem which the Button was clicked.
End Sub
You can use e.Item.DataItem to get down to the data for the object, or you could store it in a hidden field.
Building on what Mitchel said, make sure you check to see that the RowType is DataRow. Don't want to do crap when you can't. The cast from e.Item.DataItem to your type would fail on the header or footer row.

Why won't my ASP.NET CustomValidator validate?

I must be doing something wrong. I can't seem to execute my CustomValidator's ServerValidate method.
I've got a Visual Basic ASP.NET page with a CustomValidator...
<asp:TextBox ID="TextBox1" runat="server" />
<asp:CustomValidator ID="CustomValidator1" runat="server"
ControlToValidate="TextBox1"
ErrorMessage="Friendly message goes here."
Display="Dynamic" />
<asp:Button ID="Button1" runat="server"
Text="Submit"
CausesValidation="True" />
For this test, I've got the validation set to always fail...
Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
args.IsValid = False
End Sub
But, when the button is clicked, the CustomValidator1_ServerValidate() method never executes!
Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Page.Validate()
If Page.IsValid Then
'it executes the code here!
End If
End Sub
Not even if I explicitly validate that control...
CustomValidator1.Validate() 'does nothing?
What am I doing wrong?
Add the property:
ValidateEmptyText="True"
Are you putting the validator control submit button in the same validation group?
Firstly, You seem to be missing the OnServerValidate attribute in your markup above.
Secondly, I would check to ensure that CustomValidator1_ServerValidate has been set up as an eventhandler for the ServerValidate event for Textbox1. I have had occasions where I have changed the name of the validate method in the markup and code-behind, but the IDE has not auto updated the subscribing method name passed to the eventhandler delegate
I know it's a daft question (or might sound like it!). But have you actually entered or changed the value in the textbox? I think the validator won't trigger without the contents of the textbox changing.

Resources