Handling repeater events aynchronously - c#

I have a custom search control on my page (asp.net) which contains a textbox and a repeater for displaying results.
The repeater is populated with a callback as the user types ... nice and simple callback.
...
When a search result is selected the repeater fires off a postback and the itemcommand event is raised (as expected) ... and this event adds a child repeater to itself and binds a child list to the current item.
My problem is that I don't want my parent repeater to fire off a full postback because the page is quite time consuming to render.
I tried putting the control / just the outer repeater in to an ajax update panel control but it appears to still fire a ful postback.
Can anyone shed any light on how I might tell a repeater to fire its item command event in a callback instead of a postback?
I'm guessing this involves a load of manual wiring for my repeater item controls but i'm hoping theres a control somewhere that handles all that for me :)
EDIT : Sample of my situation ....
<asp:UpdatePanel ... >
<asp:Repeater ...>
<itemTemplate> <asp:LinkButton ... CommandArg='<%= Eval("ID") %>' CommandName="select" /> </itemTemplate>
</asp:Repeater>
</asp:UpdatePanel>
So my question is ...
How do i tell the repeater "fire this link buttons onclick as a callback instead of a postback"
the process of wrapping up the repeater in an update panel doesn't help because the ID of the link button is dynamic and therefore I cannot (not inline anyway) add a trigger for the link button.
If i manually add a trigger to the panel in the repeaters onitembound event i get an exception from .Net sayingt he callback reference is invalid ... i guess this is because im trying to attach a callback trigger to a control that is already handling a postback event or something setup by the repeater ...
EDIT 2 : Sample of the scenario faced here
essentially because this control X number of times on the page virtually everything has to be dynamic.
The control implements ICallbackHandler and the search bx code (not included below) fires off an ajax call onkeyup when the user types in company names (so it works a bit like google).
I was hoping that when a user clicked on a company name from the list it would ajax call back / partial postback to recover the sub list of branches thus preventing the full page flicker you get with a full postback.
Then a user would select a branch and it would do a full postback which would result in several server actions taking place.
This works fine as is ... its just not the cleanest user experience.
<div id='<%= this.UniqueID + "Results" %>' class="results">
<asp:Repeater ID="ui_lstCompanies" runat="server" onitemcommand="ui_lstCompanies_ItemCommand">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<asp:Panel ID="item" runat="server">
<li>
<asp:LinkButton ID="ui_btnSelectCompany" runat="server" CommandName="Select" Text='<%# Eval("Name") %>' />
</li>
</asp:Panel>
<asp:Panel ID="selectedItem" runat="server" Visible="false">
<li>
<hr /><h4><%# Eval("Name") %></h4>
<asp:Repeater ID="ui_lstBranches" runat="server" onitemcommand="ui_lstBranches_ItemCommand" >
<HeaderTemplate>
<table style="border-collapse:collapse;">
<tr><th> </th><th>Branch Name</th><th>Branch Address</th><th>Tel</th><th>Fax</th><th>Email</th></tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td> </td>
<td><asp:LinkButton ID="ui_btnSelectBranch1" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Select" Text='<%# Eval("Name") %>' /></td>
<td><asp:LinkButton ID="ui_btnSelectBranch2" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Select" Text='<%# Eval("Address") %>' /></td></td>
<td><asp:LinkButton ID="ui_btnSelectBranch3" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Select" Text='<%# Eval("Telephone1") %>' /></td></td>
<td><asp:LinkButton ID="ui_btnSelectBranch4" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Select" Text='<%# Eval("Fax") %>' /></td></td>
<td><asp:LinkButton ID="ui_btnSelectBranch5" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Select" Text='<%# Eval("Email") %>' /></td></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<hr />
</li>
</asp:Panel>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</div>

I had a similar problem as you did. If you replace the linkbuttons with regular asp:button and continue to use the repeater's itemcommand event as you were, it will work. Why? I don't know. However, it works. It may not look good with your design, but it triggers the asynch postback that you desired.

<asp:Repeater runat="server" ID="rpt1">
</asp:Repeater>
<asp:UpdatePanel runat="server" ID="up1">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="rpt1"/>
</Triggers>
<ContentTemplate>
<asp:Repeater runat="server" ID="rpt2">
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
This should then perform an async call to all commands from rpt1.
Just Replace these repeater control's with yours
EDIT:
I've basically created a mockup of your code with different fields etc. I assume the code below is what you tried and it was not working? If so then I've got no idea why it's not working on your side as it is on myne, there must be some slight difference somewhere that we're not picking up.
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<div id='<%= this.UniqueID + "Results" %>' class="results">
<asp:Repeater ID="ui_lstCompanies" runat="server" OnItemCommand="ui_lstCompanies_ItemCommand">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<asp:Panel ID="item" runat="server">
<li>
<asp:LinkButton ID="ui_btnSelectCompany" runat="server" CommandName="Select" Text='<%# Eval("Name") %>' />
</li>
</asp:Panel>
<asp:Panel ID="selectedItem" runat="server" Visible="false">
<li>
<hr />
<h4>
<%# Eval("Name") %></h4>
<asp:Repeater ID="ui_lstBranches" runat="server" OnItemCommand="ui_lstBranches_ItemCommand">
<HeaderTemplate>
<table style="border-collapse: collapse;">
<tr>
<th>
</th>
<th>
Branch Name
</th>
<th>
Branch Address
</th>
<th>
Tel
</th>
<th>
Fax
</th>
<th>
Email
</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
</td>
<td>
<asp:LinkButton ID="ui_btnSelectBranch1" runat="server" CommandArgument='<%# Eval("ID") %>'
CommandName="Select" Text='<%# Eval("Name") %>' />
</td>
<td>
<asp:LinkButton ID="ui_btnSelectBranch2" runat="server" CommandArgument='<%# Eval("ID") %>'
CommandName="Select" Text='<%# Eval("Address") %>' />
</td>
</td>
<td>
<asp:LinkButton ID="ui_btnSelectBranch3" runat="server" CommandArgument='<%# Eval("ID") %>'
CommandName="Select" Text='<%# Eval("Telephone1") %>' />
</td>
</td>
<td>
<asp:LinkButton ID="ui_btnSelectBranch4" runat="server" CommandArgument='<%# Eval("ID") %>'
CommandName="Select" Text='<%# Eval("Fax") %>' />
</td>
</td>
<td>
<asp:LinkButton ID="ui_btnSelectBranch5" runat="server" CommandArgument='<%# Eval("ID") %>'
CommandName="Select" Text='<%# Eval("Email") %>' />
</td>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<hr />
</li>
</asp:Panel>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</div>
</ContentTemplate>
</asp:UpdatePanel>

Related

Add multiple items to a asp repeater using tuples

I've created a repeater on the front end, and I need to add multiple items, the second item is a string and this needs to be added to the image src, any thoughts?
<asp:Repeater runat="server" ID="WeatherForcastWeek" >
<ItemTemplate>
<td>
<asp:Label runat="server" ID="Day1" />
<asp:Image runat="server" ID="WeatherIcon" />
<asp:Label runat="server" ID="Min" />
<asp:Label runat="server" ID="Max" />
</td>
</ItemTemplate>
</asp:Repeater>
Below is the DataSource type
Tuple<string, string, double, double>
You need to use ImageUrl property and pass the value using the item binding syntax for ASP.NET WebForms <%# Item.Property #>
<asp:Repeater runat="server" ID="WeatherForcastWeek" ItemType="System.Tuple`4 [System.String,System.String,System.Double,System.Double]">
<ItemTemplate>
<td>
<asp:Label runat="server" ID="Day1" Text="<%# Item.Item1 %>" />
<asp:Image runat="server" ID="WeatherIcon" ImageUrl="<%# Item.Item2 %>" />
<asp:Label runat="server" ID="Min" Text="<%# Item.Item3 %>"/>
<asp:Label runat="server" ID="Max" Text="<%# Item.Item4 %>"/>
</td>
</ItemTemplate>
</asp:Repeater>

I need to use DataList inside another DataList

<asp:DataList ID="DataListDziennik" runat="server"
DataSourceID="SqlDataSourcePrzedmioty">
<ItemTemplate>
<asp:Label ID="LabelPrzedmiot" runat="server" Text='<%# Eval("przedmiot") %>' />
...
<asp:DataList ID="DataListOceny" runat="server"
DataSourceID="SqlDataSourceOceny"
RepeatDirection="Horizontal"
OnItemCommand="DataListOceny_ItemCommandOceny"
OnEditCommand="DataListOceny_EditCommandOceny">
<EditItemTemplate>
<asp:TextBox ID="TextBoxOcena" runat="server" Text='<%# Bind("lista") %>' />
<td><asp:Button ID="ButtonZapisz" CommandName="Update" runat="server" Text="Zapisz" /></td>
</EditItemTemplate>
<ItemTemplate>
<asp:TextBox Width="20" ID="TextBoxOcena" ReadOnly="true" Text='<%# Eval("lista") %>' runat="server"></asp:TextBox>
<td><asp:Button ID="ButtonEdytuj" CommandName="Edit" runat="server" Text="Edytuj" /></td>
</ItemTemplate>
</asp:DataList>
</td>
</ItemTemplate>
When I write this in code behind:
protected void DataListOceny_EditCommand(object source, DataListCommandEventArgs e)
{
DataListOceny.EditItemIndex = e.Item.ItemIndex;
DataListOceny.DataBind();
}
Visual Studio tells me that DataListOceny does not exist in current content. I just want to be able edit items on DataListOceny after clicking the "edit" button, please give me full code in code behind part...
for edit DataListOceny .
What you asking is same like the below thread.. You need to find the DataListOceny Control on each row of DataListDziennik to bind it
Using FindControl() to find control
https://msdn.microsoft.com/en-us/library/486wc64h%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
And Here is some good example on the same
http://www.c-sharpcorner.com/UploadFile/rohatash/nested-datalist-in-Asp-Net/
http://surecode.net/DevCentre/NestedDataList/NestedDataList.aspx

how to visible false edit commandbutton inside Gridview

I am working on an asp.net application. In which i have added a commandbutton which is used to edit the row. My Gridview is
<asp:GridView ID="gvCustomerPaymentDetails" runat="server"
AutoGenerateColumns="false" ShowFooter="true" OnRowEditing="EditPayment"
OnRowUpdating="UpdatePayment" OnRowCancelingEdit="CancelEdit"
CssClass="table table-bordered table-hover" Style="margin-left: 5px; margin-right: 5px;">
<Columns>
<asp:TemplateField HeaderText="ID">
<ItemTemplate>
<asp:Label ID="lblID" runat="server" Text='<%# Eval("ID")%>'></asp:Label>
</ItemTemplate>
<ItemStyle Width="2%" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Pay Amount">
<ItemTemplate>
<asp:Label ID="lblPayAmount" runat="server" Text='<%# Eval("Pay_Amount")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtPayAmount" runat="server" style="width:100%" Text='<%# Eval("Pay_Amount")%>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtPayAmount" style="width:100%" runat="server"></asp:TextBox> </FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="linkPayNow" runat="server" Text="Pay Now" CommandArgument='<%#Eval("ID") %>' CommandName="Pay"></asp:LinkButton>
<asp:Label ID="txtStatus" runat="server" Text="Paid" Style="margin-left: 20px;" Visible="false"></asp:Label>
<asp:LinkButton ID="lnkRemove" runat="server" CommandArgument='<%# Eval("ID")%>' OnClientClick="return confirm('Do you want to delete?')"
Text="Delete" OnClick="DeletePayment"></asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="AddNewPayment" CommandName="Footer" />
</FooterTemplate>
</asp:TemplateField>
<asp:CommandField ShowEditButton="True" />
</Columns>
<EmptyDataTemplate>
<tr>
<th scope="col">Pay Amount
</th>
<th scope="col"></th>
</tr>
<tr>
<td>
<asp:TextBox ID="txtPayAmount" runat="server" />
</td>
<td>
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="AddNewPayment" CommandName="EmptyDataTemplate" />
</td>
</tr>
</EmptyDataTemplate>
</asp:GridView>
I have a Label "lblStatus" which will be either 0 or 1. If its value is 1, then i want to visible false the Update and edit commandbutton of that specific row. I have searched a lot but not found any perfect solution. Please help me someone.
In this case, I would convert the CommandField to TemplateFields. To do so, you will click on the smart tag in the gridview in design view. What this will do is change the commandfields to linkbuttons, where you can set it to false in the behind code. You will want to give your new linkbuttons proper ID's so you can find them in the behind code. Then you will create a databound method.. like..
protected void GridView1_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
//Code Here to Disable button. I'd use a Foreach loop like this.
foreach(GridViewRow gvr in GridView1.Rows)
{
Label label = ((Label)gvr.FindControl("label"));
LinkButton edit = ((LinkButton)gvr.FindControl("edit"));
if (label.Text == 1)
{
edit.Visible = false;
}
}
}
Hopefully this puts you in the right direction. I think this should do the trick.

checkbox.checkchanged event question. How do I find out which Checkbox was checked/unchanged

I'm using a Repeater:
<form id="form1" runat="server">
<div>
<asp:Repeater ID="repeater" runat="server" OnItemDataBound="repeater_ItemDataBound">
<ItemTemplate>
<tr>
<td>
<asp:CheckBox ID="checkbox" runat="server" AutoPostBack="false" OnCheckedChanged="Check_Clicked" data-id='<%# DataBinder.Eval(Container.DataItem, "ProfileID") %>'
Text="I agree" />
</td>
<td>
<asp:Label ID="lblProfileDesc" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "ProfileDesc") %>'></asp:Label>
</td>
</tr>
<br />
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="btn" runat="server" Text="Click" onclick="btn_Click" />
</div>
</form>
I'm handling onCheckedChange however how can I find out which checkbox was clicked? Thanks in advance!
You can try
CheckBox checkBox = (CheckBox)sender;
var id = checkBox.Attributes["data-id"];
Maybe you should redesign your UI architecture, as it's not acceptable to cause a full post back only for a change of a CheckBox (which is a Boolean parameter). I think you can use ajax here:
$(function(){
$('input[type=checkbox]').click(function(){
// Initializing an ajax call here, and updating DOM based on response.
});
});

Getting Failed to load viewstate error

First off, I am not dynamically creating any controls. This is the order I take to produce the error:
I have a listview on the page, when I click the edit link under the listview, I display a panel which is hidden by default. The panel has a few buttons on it along with some listboxes. When I click an item in the listbox or click one of the buttons, I get the following error:
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
Again, I am not creating anything dynamically, I am just hiding the panel with the controls by default and then displaying them, so I am not sure why I am getting this error.
Here is some code:
PAGE LOAD
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Session["Albums"] = null;
Albums = AlbumCollection.GetAlbums(Common.GetUserName(),
ddlAlbumType.SelectedIndex);
lvwAlbums.DataSource = Albums;
lvwAlbums.DataBind();
}
}
When I click the edit link, this is the code that runs:
protected void lvwAlbums_RowEditing(object sender, ListViewEditEventArgs e)
{
this.AlbumId = int.Parse(
this.lvwAlbums.DataKeys[e.NewEditIndex].Values["AlbumId"].ToString());
this.AlbumName=
this.lvwAlbums.DataKeys[e.NewEditIndex].Values["AlbumName"].ToString();
Album album = new Album(this.AlbumId);
ViewState["AlbumId"] = this.AlbumId;
ViewState["AlbumName"] = this.AlbumName;
pnlAlbum.Visible = true; // This panel holds the controls
btnEditAlbum.Visible = true;
btnCancel.Visible = true;
EditAlbum(this.AlbumId);
this.lvwAlbums.EditIndex = e.NewEditIndex;
AlbumCollection.GetAlbums(Common.GetUserName(),ddlAlbumType.SelectedIndex);
}
If I click the cancel button, I get the error, but it also happens if click another button on the panel such as Add/Remove... Here is the code for the Cancel button:
pnlAlbum.Visible = false;
this.lvwAlbums.EditIndex = -1;
AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);
Here is the aspx/html for the ListView:
<asp:ListView ID="lvwAlbums"
runat="server"
GroupItemCount="5"
DataKeyNames="AlbumId,AlbumName"
OnItemEditing="lvwAlbums_RowEditing"
OnItemCommand="lvwAlbums_ItemCommand"
OnItemDeleting="lvwAlbums_RowDeleting"
OnSelectedIndexChanging="lvwAlbums_SelectedIndexChanging"
OnPagePropertiesChanging="lvwAlbums_PagePropertiesChanging">
<EditItemTemplate>
<td>
<div>
<asp:TextBox ID="txtAlbumName" runat="server"
Text='<%# Eval("AlbumName").ToString().Trim() %>' />
<asp:LinkButton ID="lnkView" runat="server" Text="View" CommandName="View"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
|
<asp:LinkButton ID="lnkEdit" runat="server" Text="Edit" CommandName="Edit"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
|
<asp:LinkButton ID="lnkDelete" runat="server" Text="Delete" CommandName="Delete"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
<br />
<span>Songs:
<%# Eval("total") %></span>
</div>
</td>
</EditItemTemplate>
<LayoutTemplate>
<asp:DataPager runat="server" ID="ItemDataPager" PageSize="20"
PagedControlID="lvwAlbums">
<Fields>
<asp:NumericPagerField ButtonType="Link" NumericButtonCssClass="pager" />
</Fields>
</asp:DataPager>
<table>
<tr>
<td>
<table>
<asp:PlaceHolder runat="server" ID="groupPlaceHolder"></asp:PlaceHolder>
</table>
</td>
</tr>
</table>
</LayoutTemplate>
<GroupTemplate>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
</tr>
</GroupTemplate>
<ItemTemplate>
<td>
<asp:Literal ID="litAlbumName" runat="server"
Text='<%# Eval("AlbumName").ToString().Trim() %>' />
<br />
<asp:LinkButton ID="lnkView" runat="server" Text="View" CommandName="View"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
|
<asp:LinkButton ID="lnkEdit" runat="server" Text="Edit" CommandName="Edit"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
|
<asp:LinkButton ID="lnkDelete" runat="server" Text="Delete" CommandName="Delete"
CommandArgument='<%# Eval("AlbumId") %>'>
</asp:LinkButton>
<br />
<span>Songs:
<%# Eval("total") %></span>
</td>
</ItemTemplate>
</asp:ListView>
Here is the markup for the Panel:
<asp:Panel ID="pnlAlbum" runat="server" Visible="false">
<asp:ListBox ID="lstAvailableSongs" runat="server" SelectionMode="Multiple">
</asp:ListBox>
<asp:Button ID="btnAddAll" runat="server" Text="Add All" OnClick="btnAddAll_Click" />
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<asp:Button ID="btnRemove" runat="server" Text="Remove" OnClick="btnRemove_Click" />
<asp:Button ID="btnRemoveAll" runat="server"
Text="Remove All"OnClick="btnRemoveAll_Click" />
<asp:ListBox ID="lstSelectedSongs" runat="server" SelectionMode="Multiple">
</asp:ListBox>
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="btnCancel_Click" />
<asp:Button ID="btnEditAlbum" runat="server"Text="Save"
ValidationGroup="CreateAlbum" OnClick="btnEditAlbum_Click" />
<asp:Button ID="btnSaveAs" runat="server" Text="Save As" ValidationGroup="CreateAlbum"
OnClick="btnSaveAs_Click" />
</asp:Panel>
Here is some extra info:
I put an update panel around one of the listboxes in the panel and when I clicked the edit link under a listview item, I received the following error:
Microsoft JScript runtime error: Sys.InvalidOperationException: Could not find UpdatePanel with ID 'ctl00_ctl00_InnerContent_MainContent_UpdatePanel4'. If it is being updated dynamically then it must be inside another UpdatePanel.
Putting an UpdatePanel around the whole asp.net panel resolved the issue above, but I still get the Failed to load viewstate error when clicking on Cancel or Add, etc...
First off, you probably need to rebind the ListView after setting the EditIndex. (honestly, I haven't used ListView at all, but this is how the other repeater controls work) What does "EditAlbum()" do?
Your code is a little odd... why do you have the same controls in your EditItemTemplate as in the ItemTemplate? Ie, the Edit button should only be in the ItemTemplate... Then EditItemTemplate should have a Save or Cancel button.
Bottom line... your control tree is different on LoadViewState than it is when SaveViewState was called. One thing you can do is override these methods and then put a breakpoint there to manually look at the Controls collection in the debugger. You will probably see that the controls inside the ListView are different. But try my first suggestion before you do this.
Question for you:
in your Page_Load you have
Albums = AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);
but in lvwAlbums_RowEditing(..) and in btnCancel_Click(...) you have
AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);
shouldn't these be (Albums = ...)
Albums = AlbumCollection.GetAlbums(Common.GetUserName(), ddlAlbumType.SelectedIndex);

Categories

Resources