I need a way for a piece of data to presist across postbacks. Is there a way besides, cookies, and sessions?
I've got a listbox, when clicked, the selected index changed event takes a session which contains user id and feeds it to a method that fetches user's name, etc. Then I use FindControl method to locate a button inside the form view. I set the button's text property with data just fetched such as first and last name.
It works on the initial load, but if I click on other records in the listbox second time the text property is not set.
I did not write this code - I'm trying to make chages.
Here is the list box:
<asp:ListBox ID="lbxUpcommingEvents" runat="server" DataSourceID="odsUpcommingEvents"
Rows="6" DataTextField="Title" DataValueField="id" AutoPostBack="true"
Width="206px" OnSelectedIndexChanged="lbxUpcommingEvents_OnSelectedIndexChanged" />
Listbox'x on selected index changed:
protected void lbxUpcommingEvents_OnSelectedIndexChanged(object sender, EventArgs e)
{
pnlEventsSignUp.Visible = true;
string _selectedItemValue = lbxUpcommingEvents.SelectedValue.ToString();
LoadName();
}
protected void LoadName()
{
MembershipUser user = Membership.GetUser();
DataSetTableAdapters.MemberInfoTableAdapter da = new DataSetTableAdapters.MemberInfoTableAdapter();
Guid _memberId = Guid.Empty;
_memberId = new Guid(Session["myId"].ToString());
DataSet.MemberInfoDataTable dt = da.GetMember(_memberId);
if (dt.Rows.Count == 1)
{
DataSet.MemberInfoRow mr = dt[0];
RolloverLink rlnkSignUp = (RolloverLink)(fvEventSignUp.FindControl("rlnkSignUp"));
rlnkSignUp.Text = "I, " + mr.firstname + " " + mr.lastname + " will be attending this event.";
}
}
Here is markup for the form view where I set the RolloverLinkButton's text property.
<asp:Panel runat="server" ID="pnlEventsSignUp" visible="false">
<div class="dashedline" ></div>
<asp:FormView ID="fvEventSignUp" runat="server" DataSourceID="SqlDataSource1"
DataKeyNames="id" Width="100%" >
<ItemTemplate>
<h2>
<asp:Label Text='<%# Eval("title") %>' runat="server" ID="titleLabel" />
</h2>
<div class="itemdetails">
<br />
location:
<h3>
<asp:Label ID="locationLabel" runat="server" Text='<%# ShowLocationLink(Eval("locationname"),Eval("location")) %>' />
</h3>
<p>
<asp:Label Text='<%# Eval("starttime","{0:D}") %>' runat="server" ID="itemdateLabel" CssClass="GeneralText" />
<asp:Label Text='<%# ShowDuration(Eval("starttime"),Eval("endtime")) %>' runat="server" ID="Label1" CssClass="GeneralText" />
</p>
</div>
<div class="downloadevent">
<a href="#">
<img src="images/icon_download_event.gif" alt="Download this event to your personal calendar"
width="15" height="26" /></a><a href='<%# "events_download.ashx?EventID=" + Convert.ToString(Eval("id")) %>'>Add
this event to your personal calendar</a>
</div>
<Club:ImageThumbnail ID="thumb1" runat="server" ImageSize="Large" PhotoID='<%# Eval("photo") %>' />
<p>
<asp:Label Text='<%# Eval("description") %>' runat="server" ID="descriptionLabel" />
</p>
<div class="dashedline" ></div>
<asp:Panel ID="panel1" runat="server" CssClass="actionbuttons" Visible='<%#User.IsInRole("Administrators") %>'>
<table border="0" cellpadding="2" cellspacing="2">
<tr>
<td>
<asp:Label runat="server" ID="Label2" Text="Action<br />Required" Width="80px" />
</td>
<td>
<img src="images/RedArrow.jpg" alt="Red Arrow Right" />
</td>
<td>
<asp:CheckBox runat="server" ID="cbxCert" Height="30px" Text="Check to Confirm Attendance" /><br />
<asp:CustomValidator runat="server" ID="rfvConfirm"
ErrorMessage="You must check the box to continue" Font-Bold="true"
ForeColor="#cc0000" ClientValidationFunction="ensureChecked" /> <br />
<Club:RolloverLink ID="rlnkSignUp" runat="server"
/>
</td>
</tr>
</table>
</asp:Panel>
</ItemTemplate>
</asp:FormView>
</asp:Panel>
You can use ViewState. Since you are dynamically looking up the button, setting a property is quicker and we can then let Asp.Net find the button and set its text via one of the two methods I explain below:
public string rlnkSignUpText
{
get { return Convert.ToString(ViewState["rlnkSignUpText"] ?? "default value"); }
set { ViewState["rlnkSignUpText"] = value; }
}
Replace your code that searches for the button and assigns the text with:
rlnkSignUpText = "I, " + mr.firstname + " " + mr.lastname + " will be attending this event.";
Then use one of these methods to set the text to the control:
1) Use the control's OnPreRender event:
To render it, add OnPreRender="rlnkSignUp_PreRender" to your xaml like this:
<Club:RolloverLink ID="rlnkSignUp" runat="server" OnPreRender="rlnkSignUp_PreRender" />
Then in your codebehind:
protected void rlnkSignUp_PreRender(object sender, EventArgs e)
{
RolloverLink rlnkSignUp = (RolloverLink)sender;
rlnkSignUp.Text = rlnkSignUpText;
}
2) Bind the property and control together:
Instead of using the control's PreRender you can bind to the property with:
<Club:RolloverLink ID="rlnkSignUp" runat="server" Text='<%# rlnkSignUpText %>' />
You then need to call DataBind in your Page_PreRender() like so:
void Page_PreRender(object sender, EventArgs e)
{
DataBind();
}
Have you enabled ViewState in the control.
Enable View State
Related
I have added a like button on my product listview, and the like button suppose to get the value of the ads title and Adsid and the userid whose clicked on this like btn and then the code should store this add in favorite table as it mention in the code but i have a problem as i am still biggner in c# and i dont know how fix it very well could you please help with that(fix the below code cuz I am getting error message:
"Error 3 The name 'Adstitlinkbtn' does not exist in the current context
Error 2 The name 'Labeladsid' does not exist in the current context"
and aslo i will be thankfull if you add a message to user that in case if he didnt login and he click on the likebtn will recive a message " Please login to add this ads to your favorite list".
you can find this screen record that may can explain what i am meaning
screen record
Many thanks for all of you
protected void likebtn_Click(object sender, ImageClickEventArgs e)
{
SqlConnection likecn = new SqlConnection(cs);
SqlCommand likecmd = new SqlCommand();
string sqlstatment = "INSERT INTO favourite (AdsID, UID, AdsTit) VALUES (#AdsID,#UID,#AdsTit)";
likecmd.Connection = likecn;
likecmd.CommandType = CommandType.Text;
likecmd.CommandText = sqlstatment;
//Insert the parameters first
likecmd.Parameters.AddWithValue("#AdsID", Labeladsid);
likecmd.Parameters.AddWithValue("#UID", Session["UsrNme"]);
likecmd.Parameters.AddWithValue("#AdsTit", Adstitlinkbtn.Text);
SqlDataAdapter ad = new SqlDataAdapter(likecmd);
DataSet ds = new DataSet();
ad.SelectCommand = likecmd;
ad.Fill(ds);
Response.Write("This Ads has been added to your Fovarite List");
}
<asp:ListView ID="adsshow" runat="server" DataSourceID="locationdatalistshow"
style="text-align: left" >
<ItemTemplate>
<div class="templist">
<asp:Label ID="Labeladsid" runat="server" Text='<%# Eval("AdsID") %>' style="color: #ffffff"></asp:Label>
<asp:ImageButton ID="ImageButton3" runat="server" Height="88px" Width="91px"
CssClass="imag1" ImageUrl='<%# "/images/AdsImgs/" + Eval("Img1") %>'
PostBackUrl='<%# "AdsDetails.aspx?Img1=" + Eval("AdsID") %>' />
<asp:LinkButton ID="Adstitlinkbtn" runat="server"
style="font-weight: 700; color: #0066FF" Text='<%# Eval("AdsTit") %>'
CssClass="adstit" onclick="Adstitlinkbtn_Click"
PostBackUrl='<%# "AdsDetails.aspx?AdsTit=" + Eval("AdsID") %>' ></asp:LinkButton>
<br />
<asp:Label ID="AdsDescLabel" runat="server" Text='<%# Eval("AdsDesc") %>'
CssClass="adsdisc" />
<br /><br />
<br /><br />
<asp:Label ID="CountryLabel" runat="server" Text='<%# Eval("Country") %>'
style="font-family: Arial, Helvetica, sans-serif; font-size: small" />
-
<asp:Label ID="StateLabel" runat="server" Text='<%# Eval("State") %>'
style="font-family: Arial, Helvetica, sans-serif; font-size: small" />
-
<asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>'
style="font-size: small; font-family: Arial, Helvetica, sans-serif" />
<div class="adsprice">Price:
<asp:Label ID="AdsPriceLabel" runat="server" style="color: #FF0000"
Text='<%# Eval("AdsPrice") %>' /></div>
<br />
<div class="iconadsbox">
<asp:ImageButton ID="likebtn" runat="server"
ImageUrl="~/iconsimg/favoritestar2.png" OnClick="likebtn_Click" CommandName="like" />
<asp:ImageButton ID="Sndmailtoadder" runat="server"
ImageUrl="~/iconsimg/mailposter.png" OnClick="Sndmailtoadder_Click" />
</div>
<asp:Image ID="Image1" runat="server" CssClass="divideline"/>
</div>
</ItemTemplate>
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
<asp:DataPager ID="DataPager1" runat="server" PagedControlID="adsshow" PageSize="7">
<Fields>
<asp:NumericPagerField />
<asp:NextPreviousPagerField />
</Fields>
</asp:DataPager>
<br />
</div>
</LayoutTemplate>
</asp:ListView>
Create a bool value to represent whether user has logged in or not (call it bool loggedIn). Wherever your code is to login (you did not post this code), set that bool to be true. Then when the user clicks the 'like' button, in your 'likebtn_Click' method, check the bool:
if(!loggedIn)
{
MessageBox.Show("Please login to add this ads to your favorite list");
return;
}
I believe you have not shown us all your markup. It appears you are inside a grid view or some other collection control. In those controls, the template layout is dynamically generated for each item. So your label and link button controls don't really exist. What you have to do is create a GridView_Command event and in that code you will have access to the controls in that item.
So basically you created a template item and those controls are generated dynamically at runtime, which is why they are not available to you at design time. If you post the rest of your mark up me or anyone else who wants can give you more specific help.
protected void adsshow_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "like")
{
var lblAds = e.Item.FindControl("Labeladsid") as Label;
var lbtn = e.Item.FindControl("Adstitlinkbtn") as LinkButton;
var id = lblAds.Text;
var title = lbtn.Text;
}
}
<asp:ListView ID="adsshow" runat="server" DataSourceID="locationdatalistshow"
style="text-align: left" onitemcommand="adsshow_ItemCommand" >
<ItemTemplate>
...
<asp:ImageButton ID="likebtn" runat="server"
ImageUrl="~/iconsimg/favoritestar2.png" CommandName="like" />
...
Noticed I added a onCommand event to the ListView, and I removed your OnClick event from the imagebutton. I'm not 100% sure about the removing the OnClick event, so if you can please confirm for me that the OnCommand event fires correctly with the OnClick removed from the ImageButton.
I'm trying to find the values of TextBoxes which are rendered in a Repeater though a UserControl, i.e. the Repeater has a Placeholder for the UserControl, and inside the UserControl is where the TextBox markup actually exists. I've done this before with TextBoxes directly inside of a Repeater before, which was fairly straight forward, and I'm wondering why this apparently can't be accomplished the same way. Here is the Default page with the Repeater, which contains a Placeholder...
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<form class="formee">
<fieldset>
<legend>Faculty Information</legend>
<div class="grid-4-12">
<asp:Label ID="lblFirstName1" runat="server" Text="First Name"></asp:Label>
<asp:Label ID="lblFirstName2" runat="server" Text="" ></asp:Label>
<asp:Label ID ="lblSalary" runat="server" Text="" ClientIDMode="Static"></asp:Label>
</div>
<div class="grid-6-12">
<asp:Label ID="lblLastName1" runat="server" Text="Last Name"></asp:Label>
<asp:Label ID="lblLastName2" runat="server" Text=""></asp:Label>
</div>
</fieldset>
</form>
<div id="repeaterDiv">
<asp:Repeater ID="rptBudget" runat="server" ClientIDMode="Static">
<ItemTemplate>
<asp:PlaceHolder ID="phBudget" runat="server" EnableViewState="true" />
<br />
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="btnAddBudgetControl" runat="server" Text="Add"
CausesValidation="false" OnClick="AddBudgetControl" CssClass="addBudgetControl"/>
<asp:Button ID="btnDisplayEntries" runat="server" Text="Display Entries" CausesValidation="false" OnClick="DisplayEntries" />
</div>
<div>
<asp:TextBox ID="txtTotalPercent" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:TextBox ID="txtGrandTotal" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Label ID="lblCtrls" runat="server" Text=""></asp:Label>
</div>
...and the UserControl which is inserted in the place of the Placeholder...
<fieldset>
<legend>Faculty Salary Form</legend>
<table cellspacing="10" id="values">
<tr>
<td>
<asp:Label ID="lblServiceType" runat="server" Text="Service"></asp:Label>
<asp:DropDownList runat="server" ID="ddlServiceType" CssClass="serviceType" />
</td>
<td>
<asp:Label ID="lblSpeedCode" runat="server" Text="Speed Code"></asp:Label>
<asp:DropDownList runat="server" ID="ddlSpeedCode" CssClass="speedType" />
</td>
<td>
<asp:Label ID="lblPercentage" runat="server" Text="Percentage"></asp:Label>
<asp:Textbox ID="txtPercentage" runat="server" CssClass="percentCommitment" ClientIDMode="Static" EnableViewState="true" />
</td>
<td>
<asp:Label ID="lblTotal" runat="server" Text="Total"></asp:Label>
<asp:TextBox ID="txtTotal" runat="server" CssClass="amountCommitment" ClientIDMode="Static" EnableViewState="true"/>
</td>
<td>
<asp:Button ID="btnRemove" runat="server" Text="Remove Item" OnClick="RemoveItem" ClientIDMode="Static" CssClass="btnRemove" />
</td>
</tr>
<tr>
</tr>
</table>
</fieldset>
...but when the following code runs for the Display button's OnClick, I always get a null value for any and all TextBoxes (and DropDowns) in the UserControl...
protected void DisplayEntries(object sender, EventArgs e)
{
foreach (RepeaterItem repeated in rptBudget.Items)
{
TextBox txtPercentage = (TextBox)repeated.FindControl("txtPercentage");
if (txtPercentage == null)
{
lblCtrls.Text += " null; ";
}
else
{
lblCtrls.Text += txtPercentage.Text + "; ";
}
}
}
What's the best way to access these values? Thanks.
txtPercentage Textbox is located inside Usercontrol, so use the following helper method to retrieve it.
Helper Method
public static Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
return root;
return root.Controls.Cast<Control>()
.Select(c => FindControlRecursive(c, id))
.FirstOrDefault(c => c != null);
}
Usage
foreach (RepeaterItem repeated in rptBudget.Items)
{
TextBox txtPercentage =
(TextBox)FindControlRecursive(repeated, "txtPercentage");
...
}
Try loading the placeholder first and then looking for the textboxes in the placeholder:
Something like this:
pseudo
var ph = repeated.FindControl("phBudget");
var txtBox = ph.FindControl("txtPercentage");
/pseudo
You need to first get the UserControl, then use FindControl on the UC itself.
It seems I have had a lot of questions today.
What i want to do is save the text for each image.
I'm getting the right text for each picture into the textboxes at the moment.
The code behind:
var car = GarageBLL.LoadCar(Convert.ToInt32(CarId),
Convert.ToInt32(_memberId)); ImageRepeater.DataSource = car.Images;
ImageRepeater.DataBind();
protected void FinalizeNewCar(object sender, EventArgs e) {
Response.Redirect("/amcargarasjen"); }
**Code here for saving each edit into the right ImageId.**
ASP:
<asp:Repeater runat="server" ID="ImageRepeater">
<ItemTemplate>
<table>
<tr>
<td>
<a class="deleteLink" href="#" rel="<%#Eval("ImageId")%>" title="">
<asp:Image runat="server" ImageUrl="/Content/Images/Garage/DeleteButton.png" /></a>
<asp:Image Width="60" Height="45" ID="ImgCar" ImageUrl='<%# String.Format("/garageimages/{0}/{1}.{2}", CarId, Eval("ImageId"), Eval("Extension")) %>' runat="server" />
<asp:TextBox runat="server" Text='<%# Eval("Description") %>' ID="txtText"></asp:TextBox>
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
<br />
<asp:Button ID="Button1" runat="server" Text="Fullfør" OnClick="FinalizeNewCar" />
Anyone got any ideas on how to do that?
Modify your Repeater HTML markup like below. Note the addition of a Hidden field to keep the reference of the current image ID.
<asp:Repeater runat="server" ID="ImageRepeater">
<ItemTemplate>
<table>
<tr>
<td>
<a class="deleteLink" href="#" rel="<%#Eval("ImageId")%>" title="">
<asp:Image runat="server" ImageUrl="/Content/Images/Garage/DeleteButton.png" /></a>
<asp:Image Width="60" Height="45" ID="ImgCar" ImageUrl='<%# String.Format("/garageimages/{0}/{1}.{2}", CarId, Eval("ImageId"), Eval("Extension")) %>' runat="server" />
<asp:TextBox runat="server" Text='<%# Eval("Description") %>' ID="txtText"></asp:TextBox>
<asp:HiddenField runat="server" Value='<%# Eval("ImageId") %>' ID="txtImageId"></asp:TextBox>
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
<br />
<asp:Button ID="Button1" runat="server" Text="Fullfør" OnClick="FinalizeNewCar" />
CODE FinalizeNewCar Event Handler
protected void FinalizeNewCar(object sender, EventArgs e)
{
foreach (RepeaterItem item in ImageRepeater.Items)
{
Int32 imageId = Convert.ToInt32(((HiddenField) item.FindControl("txtImageId")).Value);
string description = ((TextBox)item.FindControl("txtText")).Text;
//You will get the imageId description here.
//Write your code to update the datatbase.
}
}
i to get the clientid of the control which is placed inside the Edit item template of the gridview in javascript without going to the server side code..
<asp:TemplateField HeaderText="FromDate" SortExpression="FromDate">
<ItemTemplate>
<asp:Label ID="FromDate" runat="server" Text='<%#((DateTime)DataBinder.Eval(Container.DataItem,"FromDate")).ToShortDateString()%>'></asp:Label>
<asp:HiddenField ID="ID" runat="server" Value='<%#Eval("ID") %>' />
<asp:HiddenField ID="ApproveLeaveID" runat="server" Value='<%#Eval("ApproveLeaveID") %>' />
<asp:HiddenField ID="hidLevel3" runat="server" Value='<%#Eval("Level3ManagerACENumber") %>' />
</ItemTemplate>
<EditItemTemplate>
<table>
<tr>
<td>
<asp:TextBox ID="txtFDate" runat="server" Text='<%#((DateTime)DataBinder.Eval(Container.DataItem,"FromDate")).ToShortDateString()%>'>
</asp:TextBox>
<asp:HiddenField ID="ID" runat="server" Value='<%#Eval("ID") %>' />
<asp:HiddenField ID="ApproveLeaveID" runat="server" Value='<%#Eval("ApproveLeaveID") %>' />
<asp:HiddenField ID="hidLevel3" runat="server" Value='<%#Eval("Level3ManagerACENumber") %>' />
</td>
<td>
<a onclick="showCalendarControl(3,<%# Container.ItemIndex %>)">
<img id="img3" runat="server" alt="Clock" src="../Images/clock_add.png" style="border: none" /></a>
</td>
</tr>
</table>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Left" />
<HeaderStyle HorizontalAlign="Center" />
</asp:TemplateField>
<asp:TemplateField HeaderText="ToDate" SortExpression="ToDate">
<ItemTemplate>
<asp:Label ID="ToDate" runat="server" Text='<%#((DateTime)DataBinder.Eval(Container.DataItem,"ToDate")).ToShortDateString()%>'>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<table>
<tr>
<td>
<asp:TextBox ID="txtTDate" runat="server" Text='<%#((DateTime)DataBinder.Eval(Container.DataItem,"ToDate")).ToShortDateString()%>'>
</asp:TextBox>
</td>
<td>
<a onclick="showCalendarControl(4,<%# Container.ItemIndex %>)">
<img id="img4" runat="server" alt="Clock" src="../Images/clock_add.png" style="border: none" /></a>
</td>
</tr>
</table>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Left" />
<HeaderStyle HorizontalAlign="Center" />
</asp:TemplateField>
This is my java script:
function showCalendarControl(ControlNo,index) {
var textField;
if(ControlNo==1)
{
textField=document.getElementById('<%=txtFromDate.ClientID%>');
}
else
{
textField=document.getElementById('<%=txtToDate.ClientID%>');
}
if(ControlNo==3)
{
textField=document.getElementsByClassName('txtFDate')[index];
}
if(ControlNo==4)
{
textField=document.getElementsByClassName('txtTDate')[index];
}
calendarControl.show(textField);
}
first two textbox(txtFromDate,txtToDate) is for the not in the grid control...
You can fetch the elements in the ItemDataBound event of the grid (using FindControl), and then pass the ClientID of the textbox as a parameter to showCalendarControl:
TextBox txtFDate = e.Item.FindControl("txtFDate") as TextBox;
TextBox txtTDate = e.Item.FindControl("txtTDate") as TextBox;
HtmlAnchor link = e.Item.FindControl("aLink") as HtmlAnchor;
if (txtTDate != null && txtFDate != null && link != null)
{
link.Attributes.Add("onclick", String.Format("showCalendarControl({0}, '{1}', '{2}')", 4, txtFDate.ClientID, txtTDate.ClientID);
}
(you'll also need to add an ID and a runat="server" to your link. I'm also assuming txtFDate is declared in your EditTemplate although it's not there. The ControlNo parameter could be a data key instead of a constant as in the example, it's not really clear what it is)
Then, in your function, use the clientID parameters to get the textboxes:
function showCalendarControl(ControlNo, txtFDateClientID, txtTDateClientID) {
var textField;
if(ControlNo==3)
{
textField=document.getElementById(txtFDateClientID);
}
if(ControlNo==4)
{
textField=document.getElementById(txtTDateClientID);
}
calendarControl.show(textField);
}
The problem is that every control should have unique server ID. So server side controls which are placed inside template are rendered multiple times with different auto generated ids based on ID you've specified in the template. You can easily see it if you will have a look on the generated html. Therefore your js code is accessing only the html element with hardcoded id. As I guess it is placed in the first row.
Simple solution is to describe your text box in a following way
<asp:TextBox ID="txtTDate" runat="server" CssClass="txtTDate" Text='<%#((DateTime)DataBinder.Eval(Container.DataItem,"ToDate")).ToShortDateString()%>'>
</asp:TextBox>
Then modify the js function in the following way :
function showCalendarControl(ControlNo, index) {
var textField;
if(ControlNo==3)
{
textField=document.getElementsByClassName('txtFDate')[index];
}
if(ControlNo==4)
{
textField=document.getElementsByClassName('txtTDate')[index];
}
calendarControl.show(textField);
}
And modify your link as the following :
<a onclick="showCalendarControl(4, <%# Container.DataItemIndex %>)">
Updated the answer
DataItemContainer has DataItemIndex property which has to be used in this case.
I am using listview to display a list of items and a nested listview to show list of features to each item. Both parent and child listview need to able Insert,Edit and delete operation. It works fine for parent listview. But when I try to edit an child item, The edit button does not take it into Edit mode. Can you please suggest me what I am missing in my code?
<asp:ListView ID="lvParent" runat="server"
OnItemDataBound="lvParent_ItemDataBound"
onitemcanceling="lvParent_ItemCanceling" onitemcommand="lvParent_ItemCommand"
DataKeyNames="ItemID" onitemdeleting="lvParent_ItemDeleting"
oniteminserting="lvParent_ItemInserting" >
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
<div align="right">
<asp:Button ID="btnInsert" runat="server" Text="ADD Item" onclick="btnInsert_Click"/>
</div>
</LayoutTemplate>
<ItemTemplate>
<table runat="server" cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td>
<div id="dvDetail">
<span >Description</span>
<asp:TextBox ID="txtDescription" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Description") %>' TextMode="MultiLine" ></asp:TextBox>
</div>
<div id="dvFeature" >
<span>Feature List</span>
<asp:ListView ID="lvChild" runat="server"
InsertItemPosition="LastItem"
DataKeyNames="FeatureID" OnItemCommand="lvChild_ItemCommand"
OnItemCanceling="lvChild_ItemCanceling" OnItemDeleting="lvChild_ItemDeleting"
OnItemEditing="lvChild_ItemEditing" OnItemInserting="lvChild_ItemInserting" OnItemUpdating="lvChild_ItemUpdating"
DataSource='<%# DataBinder.Eval(Container.DataItem, "FeatureList") %>' >
<LayoutTemplate>
<ul >
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" ></asp:PlaceHolder>
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<span class="dvList"><%# DataBinder.Eval(Container.DataItem, "FeatureTitle")%></span>
<div class="dvButton" >
<asp:ImageButton ID="btnEdit" runat="server" ImageUrl="/Images/edit_16x16.gif" AlternateText= "Edit" CommandName="Edit" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
<asp:ImageButton ID="btnDelete" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Delete" CommandName="Delete" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
</div>
</li>
</ItemTemplate>
<EditItemTemplate>
<li>
<asp:TextBox ID="txtFeature" Text='<%# DataBinder.Eval(Container.DataItem, "FeatureTitle")%>' runat="server"></asp:TextBox>
<div class="dvButton">
<asp:ImageButton ID="btnUpdate" runat="server" ImageUrl="/Images/ok_16x16.gif" AlternateText= "Update" CommandName="Update" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
<asp:ImageButton ID="btnCancel" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Cancel" CommandName="Cancel" Width="12" Height="12" CausesValidation="false" />
</div>
</li>
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID="txtFeature" runat="server"></asp:TextBox>
<div class="dvButton">
<asp:ImageButton ID="btnInsert" runat="server" ImageUrl="/Images/ok_16x16.gif" AlternateText= "Insert" CommandName="Insert" Width="12" Height="12" />
<asp:ImageButton ID="btnCancel" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Cancel" CommandName="Cancel" Width="12" Height="12" CausesValidation="false" />
</div>
</InsertItemTemplate>
</asp:ListView>
</div>
</td>
</tr>
<tr>
<td align="right">
<div id="dvButton" >
<asp:Button ID="btnSave" runat="server" Text="Save"
CommandName="Save"
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ItemID") %>' />
<asp:Button ID="btnDelete" runat="server" Text="Delete" CssClass="Cancel"
CommandName="Delete"
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ItemID") %>' />
</div>
</td>
</tr>
</table>
</ItemTemplate>
</asp:ListView>
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
{
BindData();
}
}
private void BindData()
{
MyDataContext data = new MyDataContext();
var result = from itm in data.ItemLists
where itm.ItemID == iItemID
select new
{
itm.ItemID,
itm.Description,
FeatureList = itm.Features
};
lvParent.DataSource = result;
lvParent.DataBind();
}
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
lvChild.DataBind();
}
Edit:
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
lvChild.DataBind();
}
If I use "lvChild.DataBind()" in 'ItemEditing' event, the total list of child items goes away if I click 'edit'
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
}
if I get rid of 'lvChild.Databind' in ItemEditing event, it goes to Edit mode after clicking the 'edit' button twice . And though it shows textbox control of EditItemTemplate, it appears as a blank textbox (does not bind existing value to edit).
This is an interesting problem. Almost certainly a databinding issue. In order to enter edit mode you must do two things:
1) Set the EditIndex
2) Call DataBind()
In the case of nested repeaters though... when does Render get called? I suspect you will have to call DataBind() on the PARENT in order to render everything correctly. That being the case you may have to then set the EditIndex AGAIN, since you are rebinding the parent.
EDIT:
OK... I just tried this with a nested GridView and I did NOT have to DataBind() the parent to get the sub grid to enter edit mode. Now I have to downvote my own answer. :|
hope that will serve someone, somewhere.
Here is my code to get that to work:
1) I have a Listview wich hold a user control when editing. This User cotnrol has itself a listview inside
<asp:ListView runat=server ID=C_LV_MyObjects DataKeyNames="Id"
OnItemDataBound=DataBoundMyObjects OnItemEditing=ItemEditing
>
<LayoutTemplate>
<table runat=server id="itemPlaceholderContainer">
<tr>
<th>
Description
</th>
</tr>
<tr runat="server" id="itemPlaceholder">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
text...
</td>
<td>
<asp:LinkButton runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</td>
<td>
<asp:LinkButton runat="server" CommandName="Delete" Text="Delete"></asp:LinkButton>
</td>
</ItemTemplate>
<EditItemTemplate>
<tr>
<td colspan=3>
<MyTag:MyUC ID=C_UC_MyUserControl runat=server
OnEditing=MyObjectEditing
/>
</td>
</tr>
</EditItemTemplate>
<EmptyDataTemplate>
No results found!
</EmptyDataTemplate>
</asp:ListView>
The code c# for this listview is as follows :
public int EditIndexComposition;
protected void ItemEditing(object sender, ListViewEditEventArgs e)
{
C_LV_MyObjects.EditIndex = e.NewEditIndex;
C_LV_MyObjects.DataBind();
}
protected void MyObjectEditing(object sender, EventArgs e)
{
ListViewEditEventArgs MyEvent = (ListViewEditEventArgs)e;
if (MyEvent != null)
EditIndexComposition= MyEvent.NewEditIndex;
C_LV_MyObjects.DataBind();
}
protected void DataBoundMyObjects(object sender, ListViewItemEventArgs e)
{
MyUC uc = (MyUC)e.Item.FindControl("C_UC_MyUserControl");
if (uc!=null)
{
uc.EditIndex = EditIndexComposition;
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
MyObject obj= (MyObject)dataItem.DataItem;
uc.DataSource=Myservice.GetDatasource(obj.Id);
uc.DataBind();
}
}
and the code of my Usercontrol is as follows :
<asp:PlaceHolder runat="server" ID="C_PH_ObjComposition">
<asp:ListView runat="server" ID="C_LV_AppaltatoreComposizione" DataSource="<% # DataSource %>"
DataKeyNames="Id" OnItemEditing="ItemEditing">
etc...
<ItemTemplate>
<tr>
<td>
<asp:LinkButton runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</td>
</tr>
</ItemTemplate>
<EditItemTemplate>
<tr>
<td>
Edit Mode
</td>
</tr>
</EditItemTemplate>
</asp:ListView>
</asp:PlaceHolder>
with the following code c# :
public int EditIndex
{
get {return C_LV_ObjComposition.EditIndex;}
set { C_LV_ObjComposition.EditIndex=value;}
}
public event EventHandler Editing;
protected void ItemEditing(object sender, ListViewEditEventArgs e)
{
C_LV_ObjComposition.EditIndex = e.NewEditIndex;
if (Editing != null)
Editing(this, e);
}
When clicking on the edit button of the innerlistview, we store the index that was clicked and we trigger a function in the first container user control. This function is going to store in a global value the index cliked and triggers a databind of the outter list. Doing so we get the onitemdatabound, that will recreate our usercontrol with the proper values, we can then before the databinding of the usercontrol assign the index of the editing row.
That's all if you have any questions , please feel free to answer..
ciao!