I hate repeating code and sometimes generics can make things a bit easier. One of the things that needs to be done a lot with Drop-down lists is adding a "Please Select" as the first option, but I don't particularly like doing that in the data layer (stored procedure, etc.). I like to add that to the list, but why repeat the same code for every Drop-down list if there are several on the page? Here is one way I like to take care of that:
Here are the supporting Classes:
01: #region Supporting Classes
02: public interface IReportObject {
03: int ID { get; set; }
04: string Name { get; set; }
05: }
06: public class CSP : IReportObject {
07: public int ID { get; set; }
08: public string Name { get; set; }
09: }
10: public class Base : IReportObject {
11: public int ID { get; set; }
12: public string Name { get; set; }
13: }
14: public class Property : IReportObject {
15: public int ID { get; set; }
16: public string Name { get; set; }
17: }
18: #endregion
Here is the method that all my Drop-down list binders will call. Notice the "new()" constraint, which is needed in order to instantiate a generic. Notice also that I'm going ahead here and changing the text based on whether or not the list is empty. It wouldn't be very helpful to have an empty Drop-down list with just a "Please Select" option and nothing else. What's not shown here is that in the presentation layer, if there are no options to select in any given Drop-down list, the control is disabled as well.
01: public static void InsertBefore<T>(List<T> list)
02: where T : IReportObject, new() {
03: list.Insert(0, new T { ID = 0, Name = ((list.Count() > 0) ?
04: "-- Please Select --" :
05: "-- No Data Found --") });
06: }
And here is one of the methods binding one of my Drop-down lists calling the method...
01: public static List<CSP> GetCSPs() {
02: var list = new List<CSP>();
03: using (SqlDataReader rs = DBAccess.getRS("cspGetMilitaryCSPs")) {
04: while (rs.Read()) {
05: list.Add(new CSP {
06: ID = DBAccess.ToInt32(rs["CSPID"], 0),
07: Name = DBAccess.ToStringValue(rs["CSPName"], string.Empty)
08: });
09: }
10: }
11: InsertBefore<CSP>(list);
12: return list;
13: }
Alas, here is another way I'm doing basically the same thing using LINQ's Union operator. Doing it this way circumvents having to call the 'InsertBefore' method:
01: protected IEnumerable<PatientData> BindPatientData() {
02: List<PatientData> opt = new List<PatientData>();
03: IOrderedQueryable<PatientData> set =
04: (from p in db.Patients
05: select new PatientData {
06: PatientID = p.PatientID,
07: PatientName = p.FirstName + " " + p.LastName
08: }).OrderBy(o => o.PatientName);
09: opt.Add(new PatientData {
10: PatientID = -1,
11: PatientName = (set.Count() > 0) ?
12: "-- Please Select --" : "-- No Data Found --"
13: });
14: return opt.Union(set.AsEnumerable());
15: }
Comments