|
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionASP.NET server controls are designed to allow for event-driven
programming and stateful behavior in the inherently stateless
environment of the web. This is a good thing as it frees the programmer from having to parse Forms and QueryStrings and instead allows the developer to address visual elements on the page (i.e. text fields, drop down lists, labels, etc.) the same way you would deal with elements in a desktop application. The result is a huge savings of time, a nearly complete separation of UI and code, and an application that is far easier to debug.
Unfortunately, many of these controls are buggy and/or missing features. Most notably, the <asp:CheckBox> control. A common scenario in web development involves a list of checkboxes next
to a bunch of items in a form. After submission of the form, the
checked items are dealt with in some way (i.e. multiple deletion of
messages in Hotmail.) Due to limitations in the CheckBox server control and a lack of documentation surrounding the proper use of Repeaters, developers have historically dealt with this problem by using a client side CheckBox, JavaScript, and an old-school cross page form post. Background The problem is fundamentally this: server side CheckBox controls lack a "Value" attribute. Therefore, it is difficult to use them with dynamically generated lists of data in a Repeater, as there is no straightforward way to determine which checkboxes represent which data item after the form is posted back. There have been many solutions posted on the web which involve re-evaluating each data item in the repeater after PostBack using a looping approach. This method is error prone (such as with forward only readers) as well as being inefficient. The method I present here instead retrieves the data only once, stores it in a hidden server control paired with the checkbox, and allows for quick and easy retrieval on PostBack The ExampleThe following snippets show a typical example where a customer list is displayed, with a checkbox next to each customer. After the user clicks a button, messages are sent only to the customers who they have checked off. The Front-End Code <asp:Repeater id="customerList" runat="server">
<ItemTemplate>
<%# Eval("name") %><br /> <!-- Their name -->
<%# Eval("email") %><br /> <!-- Their email -->
Send mailing list invite <asp:CheckBox id="selectUser" runat="server">
<!-- Line below is key -->
<asp:HiddenField ID="hiddenEmail" Value ='<%#Eval("email")%>'>
</ItemTemplate>
</asp:Repeater>
<asp:Button Text="Send Message" OnClick="DoSend" Runat="server" />
What we have done here is to place an invisible server control, the asp:HiddenField, inside the Repeater template. Since this control DOES allow a value to be assigned to it, we can now determine which checkbox is linked to which row. To retrieve the email addresses associated with the checked items after PostBack, we need only to use a simple loop, as follows: The Code-Behind public void DoSend(object sender, EventArgs e)
{
foreach (RepeaterItem i in customerList.Items)
{
CheckBox cb = (CheckBox)i.FindControl("selectUser");
if (cb.Checked)
{
HiddenField hiddenEmail = (HiddenField)i.FindControl("hiddenEmail");
SendWelcomeMessage(hiddenEmail.Value);
}
}
} And that's all, folks! May the "I want to bang my ahead against the wall because I can't use a checkbox insider a repeater" phenomenon be but a distant memory. Points of Interest Microsoft has put a lot of work into its GridView control (for example, this particular problem is not an issue there) but really neglected its Repeater, which hasn't even changed significantly since ASP.NET 2.0. Many coders choose the GridView over the Repeater partly for this reason. Repeaters are far more lightweight, and allow for full control over what is rendered. Hopefully this workaround will help to encourage its use.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 16 of 16 (Total in Forum: 16) (Refresh) | FirstPrevNext |
|
|
 |
|
|
You may want to put attributes inside the server control:
<asp:checkbox myattribute="<%#(Container.DataItem as Person).PersonID" runat="server" />
And in the codebehind:
foreach(RepeaterItem i in repeater1.Items) { CheckBox chk = FindCheckBox(i); int personID; if (!int.TryParse(chk.Attributes["MyAttribute"], out personID) { //TODO: Error handling on parsing the value } Response.Write(string.Format("PersonID selected: {0}", personID)); }
Sure is not the correct way of use, but in my opinion is fast than inherit the checkbox and implement the custom attributes. This approach have the aspect that you send the personid to the client browser:
<input type="checkbox" myattribute="123whatever" id="ctl0_control1_checkbox1" />
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I recall this method not working for me. The IDs were sent to the browser, but were empty when I tried to retrieve them afterwards in the code behind.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You tried the following?
public void Page_Load(object sender, EventArgs e) { //Attach to event. This attach method only works with .net 2.0. If you need the 1.1 version, please encapsulate the method into the RepeaterItemEventHandler delegate; repeater1.ItemDataBound+=repeater1_ItemDataBound; } protected void repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e) { //find the right control to change its attributes CheckBox chk = FindCheckBox(e.Item); //Since we have the Attributes being set in the server side, the control persists them in the viewstate, so in the postback, it will be available. chk.Attributes["PersonID"] = (e.DataItem as Person).PersonID.ToString(); } Im almost sure this will work. If you try and resolves the problem, please let us know by updating the article. Thanks for the article and sorry my awful english.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Zing. Absolutely. Article should be renamed "The hacky and thoughtless way to use checkboxes in a .net Repeater"
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey, be nice... it's less hacky and thoughtless than any of the other solutions you'll find posted, which involve attempting to add atttributes when each item is databound.
Inheritance sounds like an even cleaner solution; however it would take longer to set up. I'll try it and compare that solution with this in a profiler and get back to you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sorry if I was crass, but telling people that 'this is the RIGHT way' is misleading. And beginners will take your advice to heart, and then you have misguided programmers who think they are going about things properly.
As far as a inherited class, 'longer to setup' isn't really true, this should do it, but I havent compiled it:
/// <summary> /// A checkbox control that has a bindable viewstate backed value property /// </summary> [ToolboxData("<{0}:ValuedCheckBox runat=\"server\">"), ToolboxBitmap(typeof(CheckBox))] public class ValuedCheckBox : CheckBox { [Bindable(true), Category("Data")] public object Value { get { return ViewState["Value"]; } set { ViewState["Value"] = value; } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thing is, most front end ASP.NET coders are not skilled in the more esoteric features of C#, and many don't understand inheritance - they understand how to consume and manipulate the objects that the more hardcore programmers have written in the App_Code but many will never even write a class themselves - they don't need to.
Now if MS included a checkbox with a value attribute built in, obviously I would favour its use. Damn, someone should email this whole discussion to the ASP.NET team over there and maybe they'd realize that they should fix the control! (which is the one thing I'm sure we agree on here
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
esoteric? Inheritance?
If these these types of devs are struggling, it's not because they are 'front end asp.net developers', but it's because of the lack of knowledge in the very basic principles of the .net framework and ASP.NET.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I go with you 'evolved'! If you dont know how to extend a class, im sure you're programming the wrong language, i encourage all of them to go back to asp 3.0/vb 6.0. Im sure you'll be more productive. Or, if you really want to, please study more, read more codeproject articles and be more responsible when posting new articles. Im not flaming or rating the article, only trying to explain that if you dont know how to do something, go to forums and post there.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You obviously don't work for a social networking site, where the front end changes so often, it would simply be impractical to encapsulate everything. We are talking weekly releases of new UI features, occasionally midweek releases as well. For major, core features involving the database or the DAL, we work in a disciplined, object oriented manner.
But for the front end, what is important is that the code be (a) readable, and (b) changable. And the material that you have posted is not.
Don't tell me that you have that syntax memorized, because you don't. It's the kind of thing you have to look up. The last thing you want on the day of a launch is to have to go and look up how to modify a class with weird syntax written by some developer who left a long time ago. My solution, on the other hand, could be understood by a new hire even if I was not around to explain it to them.
Sorry to be confrontational about this, but I really think that the unprovoked rudeness shown by yourself and evolved is really inappropriate for a community that's supposed to be about developers learning from each other and working together.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Damn english!!! Sometimes i cannot explain myself. The solution you provide (about making the hidden field), is not the best design pattern, far from that. You have to know that you need to develop the softwares in the time you project manager gave to you. This make us do weird things that just works, developing faster than making inheritance, extending controls and so on. I cant judge if my code snippet is more or less readable than yours. It depends of the team knowledge. I think the code is readable because i use with certain frequency and yours code isnt so intuitive, because: The input hidden is not strongly typed and does not exists at design time. BUT it works, ok! My post is not for flaming and offending other people who dont know the language features. There are many ways to achieve the desired result, and the best is the fastest and easier maintenance.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Alright Sam, I waited a while to post back because I wanted to make sure I understood everything you said here and I didn't want to misinterpret.
1) The syntax memorized? Absolutely, to be honest, the only thing I looked up was the designer toolbox bitmap attribute. I only looked this up because I wanted the code fragment in your misleading article to actually be used by beginners who are only looking for a code snippet. Do you really thing that even a budding programmer doesn't know the syntax in C# to do the following: inherit from a base class, and add a viewstate backed property? You are sincerely misguided.
2) Sure, the 'front end guys' you speak of might not make this class. I guess thats where your view of them differs from mine. Instead of ugly hacks in asp.net to get things accomplished, the proper way is to create a class that does what you need. So, in this situation, I have a class library of custom server controls and user controls to accomplish just that. Instead of "here use only the core asp.net controls and use your own deficient programming skill to warp it into you need", i'd say "here's a class library of controls that we have crafted over the years, if there is something lacking in them, feel free to look at the source code or ask a more experienced programmer to change them".
3) "The last thing you want on the day of a launch is to have to go and look up how to modify a class with weird syntax written by some developer who left a long time ago."
Hrmm, the Repeater class and Checkbox classes are both classes with wierd syntax written by some developer who may have left microsoft a long time ago. 'Wierd syntax'? A value property? Thats bindable? And has xml documentation to aid in autocomplete?
I don't know if your trolling me, or just refuse to see that hacking asp.net to get it to do awkward things is not sustainable, especially in a larger project with multiple developers. To be honest, if I had to check out this code during a code review, I would state that it was designed poorly and implimented improperly, and recommend whoever made it review the simple syntax that the framework guidance and microsoft patterns and practices tell us .
I understand if you feel this is too difficult. In my opinion having the desire to learn more about any programming language or framework I use in my job is one of the reasons why I'm not what you call a 'front end developer'
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm trolling you? You're the troll in this one. If you worked for me, and I had the pleasure of doing your annual performance review, I would recommend that you learn how to work with other people and stop talking down to them. Then I would toss your ass out the door, and you would go work for some faceless fortune 500 company and spend the rest of your life rotting in some cubicle making custom controls for some site that lets people pay their bills online, purchase life insurance, or do some sort of equally boring activity.
Its not that I don't think you have a valid argument in favor of inheritance and encapsulation, it is that you are the developer equivalent of one of those religious fundamentalists who tells everyone who disagrees with them that they're going to hell.
p.s. I would be bitter like you if I had to work on software that keep track of such exciting things as dog ownership licensing and municipal tax code enforcement. http://www.spatialdatalogic.com/sdl/sol_Pet.aspx[^]
modified on Friday, April 11, 2008 2:05 PM
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
Good article, but just a bit of a nit pick...
You state "Many coders choose the GridView over the Repeater partly for this reason. Repeaters are far more lightweight,..."
The repeater has a dark side and is a late binding control and uses a lot of reflection, which make things a lot more slower, one way to help with the reflection issue is not to use <%=Eval("FieldName")%> but use <%#((System.Data.DataRowView)Container.DataItem)["FieldName"] %> instead....
I use the repeater alot because it is eaiser for designers to visualise and use the hidden field approach for checkboxes.
Hope this helps. Source google: Scott Allen
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The Eval was just to simplify the example - I am generally binding to collections anyways and casting the Container.DataItem.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|