Pass object as CommandArguement in a Repeater Link Button - c#

I have a Repeater with a list of Customers. Against each customer there is a delete link button. As part of the linkbutton I want to pass the Customer object to the Command Arguement as follows (where Container.DataItem is the customer object):
<asp:LinkButton ID="lnkDelete"
OnClientClick="return confirmDelete();"
OnClick="Customer_OnDelete"
CommandArgument="<%# Container.DataItem %>"
CommandName="Delete"
runat="server"></asp:LinkButton>
When I do this:
var button = (((LinkButton) sender));
var customer= button.CommandArgument;
button.CommandArguement is a string. I need all the object properties as we are using Nhibernate so everything needs to be set, the ID of the deleted record is not enough. I have seen examples online regarding passing a comma seperated list of values into the command arguement but want to avoid doing that. Is this possible?
Any ideas?
Thanks

In my opinion the best way for this case is:
Get the ID from CommandArgument
Get the Customer by ID
Delete the Customer Entity
Use the Repeater event OnItemCommand. This event contains RepeaterCommandEventArgs. You cant get the CommandArgument this way:
protected void myRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
int customerID= Convert.ToInt32(e.CommandArgument.ToString());
}
At your asp:LinkButton tag use:
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ID") %>'

The issue you are running into here is that you repeater has to get translated into HTML. Therefore you are constrained to the limits of what is allowed by the specification in an element attribute.
On the server side CommandArgument will always be a string, so you cannot do what you want as you have it coded.
Now... there are several hacks you could implement to get around this, like the aforementioned CSV, or you could use binary serialization and Base64 encode the result. However, these are all terrible solutions!
What you need is to re-think how you are doing this. I promise there is an easier way.

Related

Dynamically create textbox based on amount of strings in array

I am iterating through an array of strings.
For each string I need it to be presented in a new textbox on the web page.
I have got this working by just having one textbox available, however this worked as a proof of concept. My problem being I am dealing with larger arrays now, with a varying amount of strings.
Is there a method to dynamically create textboxes on the page in relation to how many strings there are?
Here is what I have so far-
protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
{
WebService1 ws = new WebService1();
foreach (string x in ws.mRETURN(CheckBoxList1.SelectedItem.Text))
{
TextBox1.Text = x;
}
}
So textbox one already exists on the page, however I know need it to be dependant on how many strings there are being passed from the webservice, and relate this number to the amount of textboxes needed.
Try this
Markup
<asp:DataList runat="server" ID="repeatedTextBox">
<ItemTemplate>
<asp:TextBox ID="myTextBox" runat="server" Text='<%# Container.DataItem.ToString() %>'></asp:TextBox>
</ItemTemplate>
</asp:DataList>
Codebehind
repeatedTextBox.DataSource = myChangingArrayOfString; //e.g ws.mRETURN(CheckBoxList1.SelectedItem.Text)
repeatedTextBox.DataBind();
How about using a placeholder on the webpage and adding controls(TextBoxes) to it programatically.
<asp:PlaceHolder id="Area1" runat="server"></asp:PlaceHolder></P>
Then on your back end add:
TextBox tbx = new TextBox();
Area1.Controls.Add(tbx);
In a loop you could do that?
I am still learning so its my best suggestion at this stage.
Derived from source: Source

how to access repeater label value in javascript

This is my javascript
function btnEditClick() {
alert(document.getElementById('<%=LblRefPhyID.ClientID %>').value);
}
<asp:Repeater ID="repeaterRefPhysicianList" runat="server">
<ItemTemplate>
<tr onclick="selectRow(this);">
<td class="csstablelisttd" style="display: none;">
<asp:Label ID="LblRefPhyID" runat="server" Text='<%#Eval("Ref_Phy_ID")%>'></asp:Label>
</td>
on clientclick of Edit button i have to pass RefphyId to another page how can i do that..
It's a repeater. That means that the ItemTemplate will be repeated for each item in your databound collection.
This comes with a caveat: IDs are supposed to be unique. So when you say that your asp:Label has an ID of LblRefPhyID, ASP.NET automagically does you the favor of generating unique IDs for each instance of the repeater that eventually makes its way to your generated HTML. These generated IDs will be based on your original value of LblRefPhyID, but it won't be exactly that, so a plain document.getElementById() outside of the repeater won't work.
There are many ways to work around this, and the very first step you need to do is to actually write some code that will take the automatic generated IDs into account. Maybe write some Javascript to cache the IDs using LblRefPhyID.ClientID, maybe do it dynamically onclick, whatever.
EDIT
And, oh yeah, #Pointy is completely correct in stating that label elements don't have values, just their inner HTMLs. I don't get why he got downvoted for giving a correct response.
Try to set css class instead of id and bind elements click event by class name.
I'm using jquery for this:
$(document).ready(function(){
//bind click event on our label class
$('.lblRef').live('click', function(){
alert($(this).text());
});
});
And this in asp.net page code:
<asp:Label CssClass="lblRef" runat="server" Text='<%#Eval("Ref_Phy_ID")%>'></asp:Label>
HTML <label> elements don't have a "value". They do have contents:
alert(document.getElementById('<%=LblRefPhyID.ClientID %>').innerHTML);
Best way would be to check what is the pattern of id generated by the repeater on the client side and then you can use that id to get the value of the label using innerHTML.
For instance in your case id generated may be :
repeaterRefPhysicianList_LblRefPhyID_01 to till the number of rows in source.
So you can use this information with innerHTML to get the value of the label..
All in all just check your html page you will know what to do next :)

Creating binding in codebehind

I have this type of code in aspx but wish to generate it in code behind. What would be the equivalent?
<uc1:editformcontrol ID="EditFormControl1" runat="server" CategoryID=' <%#Bind("CategoryID") %>' />
The question pertains mainly to the binding
It's difficult to say without knowing your data model. What kind of data source are you using? You could try adding this line to the Page_Load method:
int categoryId;
categoryId = WHEREEVER YOU'RE STORING THIS VALUE...
EditFormControl1.CategoryID = categoryId;
Usually, you override the OnDataBound event on your control and bind the data there.
See here one example.

Updating asp:SqlDataSource Parameter via asp:LinkButton

I'll try to explain what I'm doing the best I can, but I'm pretty new to asp.net so be patient with me.
I have a SqlDataSource which returns a simple select statement based on the WHERE clause using #COURSE_ID
What I want to-do is every time any one of 2 (this will change as it's going to be generated) asp:LinkButtons are pressed, they will change the #COURSEID value which i'd like to associate with the specific button.
Buttons:
<asp:LinkButton ID="LinkButton2" runat="server" onclick="MenuUpdate_Click">Course1</asp:LinkButton>
<asp:LinkButton ID="LinkButton1" runat="server" onclick="MenuUpdate_Click">Course2</asp:LinkButton>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:connString %>" SelectCommand="SELECT Chapter.chapterName, Chapter.chapterID
FROM Chapter
WHERE Chapter.courseID = #COURSE_ID
">
C#
protected void MenuUpdate_Click(object sender, EventArgs e)
{
Parameter p = SqlDataSource1.SelectParameters["COURSE_ID"];
SqlDataSource1.SelectParameters.Remove(p);
SqlDataSource1.SelectParameters.Add("COURSE_ID", THIS NEEDS TO BE VALUE ASSOCIATED TO BUTTON);
ListView1.DataBind();
UpdatePanel1.Update();
}
If anyone has any suggestions that'd be great, I've been trying lots of different things all night with no success :(
Thanks
Try setting the linkbutton IDs to contain the course name (I dont think its possible for IDs to start with numbers, so give them IDs "crs" and then the course name). In the click event for the buttons, extract the ID of the sender and take the entire string after "crs". This is the course name of the linkbutton that was clicked.
Also if "COURSE_ID" is the only parameter of the SelectCommand, I would personally clear all the parameters first. It just ensures that you dont have any parameters from elsewhere. Thats just the way I work though - clear everything and reenter anything which shouldnt have been cleared and then enter anything extra.
Regards,
Rich

SqlReader, Repeater controls and CommandArgument problem

I have a repeater control that generates a list of links from a SqlReader. I'm trying to create a button alongside each link that will allow the user to delete that link. My original thought was to use the <%#Eval("URL") %> expression in the Item template like below. However the CommandArgument in the ItemCommand method would always come back empty.
<asp:Repeater ID="rptLinks" runat="server" onitemdatabound="rptLinks_ItemDataBound"
onitemcommand="rptLinks_ItemCommand">
<ItemTemplate><%# DataBinder.Eval(Container.DataItem, "URL") %><asp:ImageButton visible="false" ID="btnDeleteLink" runat="server" ImageUrl="/Images/DeleteIcon.gif" CommandName="DELETE" CommmandArgument=<%#Eval("URL") %> />
</ItemTemplate>
<SeparatorTemplate><br /></SeparatorTemplate>
</asp:Repeater>
The next thing I tried was to use the ItemDataBound event to programatically set the CommandArgument, but I can't figure out what to cast the e.Item.DataItem into so I can reference the ["URL"] Item.
protected void rptLinks_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
ImageButton btnDelete;
btnDelete = (ImageButton) e.Item.FindControl("btnDeleteLink");
if (btnDelete != null)
{
btnDelete.Visible = (bool)ViewState["LinkEditing"];
string URL = ((WhatTypeGoesHere)(e.Item.DataItem))["URL"].ToString();
btnDelete.CommandArgument = URL;
}
}
You can cast the DataItem to any of the classes in your reader's inheritance chain that implement IDataRecord:
// You could also cast to SqlDataReader, DbDataReader, or IDataReader
string URL = ((IDataRecord)(e.Item.DataItem))["URL"].ToString();
Data readers are a bit confusing, because objects that inherit from DbDataReader can act as both a data source (through its implementation of IEnumerable) and as the object representing your data (through its implementation of IDataRecord).
The IDataRecord interface provides access to the column values of a data reader's records (via the Item property and the various Get* methods).
In other words, it's like you're binding to an IEnumerable<IDataRecord> (though not really, because DbDataReader implements the non-generic version of IEnumerable).

Categories

Resources