ASP.NET ListView control not firing OnItemCommand Event - c#

I know that this sounds like a number of other posts, all of which I have read but have not addressed my issue.
Here's the Scenario ...
I have BOTH a Repeater and a ListView bound to the same Data Source. Each control contains an ASP:LinkButton which, when clicked, should fire the OnItemCommand event. Although they are wired to the EXACT same data at the EXACT same places in the page life cycle and View State is enabled for the page and each individual control the Repeater appears to fire the event and the ListView does not.
I know that the event will not fire if the data is not bound BEFORE the assignment of the event handler. I am relying on ViewState to repopulate the controls when the page is posted back to. Looking at each control in debug mode while stepping through a request I can see that the Repeater DOES indeed appear to repopulated with the ViewState data but the ListView does not.
As these are both generated, populated, bound, and handled almost IDENTICALLY I am at a complete loss why this may be happening. I have also noticed a similar issue with the GridView control (it does NOT fire the event). I assume that these are related somehow.
The only thing that I can think of that the GridView and ListView have in common that the Repeater does not is the built-in paging capability. Whether implemented or not is there something with the paging that affects the loading of the ViewState?
OrderControl.ASCX is a control which exposes the ListView and Repeater as properties (OrderListLV & OrderListRPT) to the host page/application.
<asp:ListView runat="server" id="lvOrderList" OnItemDataBound="lstOrderList_OnItemDataBound" EnableViewState="true" >
<LayoutTemplate>
<table class="tblGrid">
<tr runat="server" id="itemPlaceholder" />
</table>
<ASP:DataPager runat="server" ID="dataPager1" PageSize="3">
<Fields>
<ASP:NextPreviousPagerField
ButtonType="Button"
ShowFirstPageButton="true"
ShowLastPageButton="true"
ShowNextPageButton="true"
ShowPreviousPageButton="true" />
</Fields>
</ASP:DataPager>
</LayoutTemplate>
<ItemTemplate>
<tr class="row-">
<td align="center"><ASP:LinkButton runat="server" id="lnkOrderId1" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:Repeater runat="server" id="rptOrderList" OnItemDataBound="rptOrderList_ItemDataBound">
<HeaderTemplate>
<table class="tblGrid">
</HeaderTemplate>
<ItemTemplate>
<tr">
<td align="center"><ASP:LinkButton runat="server" id="lnkOrderId" /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
OrderControl.ASCX.CS is where the controls are bound to the data source in the Pre-Render stage, well after ViewState has had the opportunity to reconstitute itself.
protected override void OnPreRender(EventArgs e)
{
this.lstOrderList.DataSource = this.OrderHeaders.OrderByDescending(x => x.OrderDate).ToList();
this.lstOrderList.DataBind();
this.rptOrderList.DataSource = this.OrderHeaders.OrderByDescending(x => x.OrderDate).ToList();
this.rptOrderList.DataBind();
}
Host.ASPX.CS is the page which consumes the control. It attaches the event handlers directly the controls in it's OnLoad handler.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.OrderControl.OrderListRPT.ItemCommand += new RepeaterCommandEventHandler(OrderList2_ItemCommand);
this.OrderControl.OrderListLV.ItemCommand += new EventHandler<ListViewCommandEventArgs>(OrderList_ItemCommand);
}
After all is said and done when I click on the LinkButton in each control the ItemCommand Handler for the Repeater fires and executes correctly but the process doesn't even enter the handler for the ListView handler.
I am crazy confused on this issue. I am hoping that someone might have some thoughts on this. Something I can try at least?
Thanks,
Gary

you should set the CommandName property of each LinkButton in the ListView, eventually also the CommandArgument.
<td align="center">
<asp:LinkButton runat="server" id="lnkOrderId1" CommandName="yourCommandName" CommandArgument="yourCommandArgument" />
</td>
also check asked questions here in SO before posting a new question ;-)
listview OnItemCommand dosen't fire up

Related

How to find which control triggers the event inside a repeater

How to find which control event got triggered, for example, if there are 5 columns in the repeater if the 2nd checkbox or 3rd drop-down list causes the event. How to find which control event got triggered, so that the particular control related logic alone will be executed without disturbing other column controls.
The sample repeater code is attached as follows,
<asp:Repeater ID="rptTest" runat="server">
<ItemTemplate>
<td class="repeater-col">
<div>
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
</div>
<div>
<asp:DropDownList ID="ddl1" runat="server" OnSelectedIndexChanged="ddl1_SelectedIndexChanged" AutoPostBack="true">
</asp:DropDownList>
</div>
<div>
<asp:CheckBox ID="chk1" runat="server" OnCheckedChanged="chk1_CheckedChanged" AutoPostBack="true" />
</div>
</td>
</ItemTemplate>
</asp:Repeater>
There are lot more dependent controls presented inside the repeater. Based on the selection of the controls the data to the other controls are bound and processed. The logic bounded to the repeater will be handled on the respective events for example on chk1_CheckedChanged and ddl1_SelectedIndexChanged
Kindly help on this! Thanks in advance!
You can cast the sender back to the correct Control type. Then you can access it's properties. If you want to know which items the control was in, you can use the NamingContainer
protected void ddl1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList drp = sender as DropDownList;
drp.BackColor = Color.Green;
RepeaterItem item = drp.NamingContainer as RepeaterItem;
int itemIndex = item.ItemIndex;
}

How to avoid post-back of Check Box inside repeater

I am newbie for asp.net,
I have a repeater which contains check box,whenever I check the check box I am firing an event on checkchanged,but the page postbacks.
I have an update panel for the entire content in my page,but still postback occurs.Is there anyway to avoid postback.
(Ps:To avoid Postback,I am meaning to avoid the flicker that occurs)
Thanks
<asp:Repeater ID="rptrDepartment" runat="server" OnItemCommand="rptrDepartment_ItemCommand"
OnItemDataBound="rptrdepartment_databound">
<ItemTemplate>
<tr>
<td>
<asp:CheckBox ID ="chkRow" runat="server" OnCheckedChanged="ChkRow_ChkChanged" AutoPostback="true" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
And in my .cs page,
protected void ChkRow_ChkChanged(object sender, EventArgs e)
{
//some method
}
Just keep your repeater inside update panel rather than entire page, if you want some other controls also need partial postback then you can go for multiple update panels.

Sorting Listview

I have A listview which I want to sort.
My problem is that when I click the sorting column the Onsorting event only fires when I Bind the data on pageload again.
This means that on every pageload I will first have to bind the data, then I can catch the OnBinding event and after that I can Rebind the data again.
Is there a better way to do this. Basically what I want is to bind the data only in the onsorting event
<asp:ListView ID="TempList" runat="server" OnSorting="TempList_sorting">
<LayoutTemplate>
<table >
<tr>
<th >
<asp:LinkButton runat="server" ID="btnSortVoorletters2" CommandName="Sort" Text="Voorletters"
CommandArgument="Voorletters" OnClick="btnSortVoorletters_Click" />
</th>
</tr>
<tr runat="server" id="itemPlaceholder">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="EmpIDLabel" runat="server" Text='<%# Eval("Naam") %>'/>
</td>
</tr>
</ItemTemplate>
<EmptyDataTemplate>
<p>Empty text that will be displayed.</p>
</EmptyDataTemplate>
It lloks that you're always binding in PageLoad so that the previously supplied order is lost. Bind only if IsPostback is false. (You need to have the ListView EnableViewState set to true, which is the default value).
if(!IsPostback)
{
// do the binding
}
When the user clicks the 'Sort' button, the event will be fired and your event will sort and bind the data accordingly.
If the page is reloaded, and you don't rebind it in PageLoad this will be enough.
However, if for some reason you really need to rebind in PageLoad, what you have to do is to store the sorting in ViewState, a HiddenField or Session so that you can get the value from there to sort the data before binding it in PageLoad.
You should take the code that sorts and binds to a new method, and call it from both the Sort and the PageLoad events.

How Do I Get a Dynamic Control's Value after Postback?

I have a listview that adds controls in the ItemDataBound Event. When the postback occurs, I cannot find the new controls. After a bit of research, I found that ASP .NET needs these controls created every time, even after postback. From there I moved the function to bind the ListView outside of the if (!Page.IsPostBack) conditional. Now I get the dynamic controls values but the static controls I have are set to their defaults. Here is a sample of what I am trying to accomplish:
For brevity, I left some obvious things out of this example.
<asp:ListView runat="server" ID="MyList" OnItemDataBound="MyList_ItemDataBound">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</LayoutTemplate>
<ItemTemplate>
<asp:PlaceHolder runat="server" ID="ProductPlaceHolder">
<asp:TextBox runat="server" ID="StaticField" Text="DefaultText" />
<asp:PlaceHolder ID="DynamicItems" runat="server" />
</asp:PlaceHolder>
</ItemTemplate>
</asp:ListView>
and here is the codebehind:
protected void MyList_ItemDataBound(object sender, System.Web.UI.WebControls.ListViewItemEventArgs e) {
PlaceHolder DynamicItems = (PlaceHolder)e.Item.FindControl("DynamicItems");
DynamicItems.Controls.Add(textbox);
}
So, like I said, if I only databind when Page != PostBack then I cant find my dynamic controls on postback. If I bind every time the page loads then my static fields get set to their default text.
Try moving the data binding of the ListView into the OnInit() event.
Very similar question (instead of populating a ListView the guy is generating a set of buttons). Briefly, you'll find that you have to store the items in the list in your Viestate - than fish it out on Postback and re-populate the list.
Note that this solutions implies dropping data-binding (which you might not wanna do for others reasons).
Hope it helps.

ASP.net ListView Access controls in ItemUpdating event

I'm missing something here...
I need to access the values of the controls on the item that is leaving editmode, thus firing ItemUpdating.
I found how to get the key value so I know which record in the database I have to update. The problem is that I can't seem to access the values of the controls on the editing row.
the EditTemplate contains a few checkboxes, a dropdown and textbox. I need to access these values so I can update the record.
When looking at the eventargs, nothing shows.
I think I'm overlooking something crucial here, any help would be handy.
You can also use "ListView.EditItem.FindControl("X")" to access control directly.
Protected Sub ListView_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewUpdateEventArgs) Handles ListView.ItemUpdating
Dim DropDownListddl As DropDownList = ListView.EditItem.FindControl("DropDownListddl")
Lblwarning.Text = DropDownListddl.SelectedValue
End Sub
There are two ways I can think to do this.
The first way would be to use a datasource that supports an update command and using two way binding to up date the values. The following snipped uses two way binding to populate the name and student fields and it will also update them for you.
<EditItemTemplate>
<tr style="background-color: #FFCC66;color: #000080;">
<td>
<asp:Button ID="UpdateButton" runat="server" CommandName="Update"
Text="Update" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel"
Text="Cancel" />
</td>
<td>
<asp:TextBox ID="nameTextBox" runat="server" Text='<%# Bind("name") %>' />
</td>
<td>
<asp:TextBox ID="studentTextBox" runat="server" Text='<%# Bind("student") %>' />
</td>
</tr>
</EditItemTemplate>
If you are not using a datasource that supports this you can do one other thing.
Notice how the update button has a command called "Update". You can use this to fetch the control values you want by handling the list views ItemCommand Event.
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "Update")
{
TextBox box = (TextBox)e.Item.FindControl("nameTextBox");
string name = box.Text;
}
}
You can find any control in the editied item by simply calling find control and passing it the control's ID, and don't forget the cast.
Hope this helps

Categories