Archive for May 2013

Objective-c for iOS Cheat Sheet

This Objective-c for iOS Cheat Sheet is written for my midterm for my Masters of Computer Science course on iOS Mobile Development. The class didn’t fill up like I thought it should. Perhaps that has to do with the fact that the class name was misspelled as ISO Mobile Development. Oops.

Creating an objective-c class

  1. All objects should inherit NSObject which is found in Foundation.h.
  2. Objects should be created in the following two files.
#import <Foundation/Foundation.h>
@interface MyObject : NSObject
@end
#import "MyObject.h"
@implementation MyObject
@end

Adding a local variable to an objective-c class

A variable is added to the .h file that is only used by the code in the .m file.

#import <Foundation/Foundation.h>
@interface Person : NSObject
{
    string name;
}
@end
#import "Person.h"
@end

Adding a property to an objective-c class

A property is a short cut for a variable wrapped in a getter and setter.

  1. Add an @property line in the .h file as shown below.
  2. Add an @synthesize line for the property in the .m file as shown below.
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property string name;
@end
#import "Person.h"
@implementation Person 
@synthesize name;
@end

Adding a method to an objective-c class

Here is an example of two methods:

  1. a method without a parameter
  2. a method with two parameters.

In many other languages, these methods signatures would look as follows:

double getPI();
double add(double x, double y);

In ojbective-c, the methods look like this:

#import <Foundation/Foundation.h>
@interface calc: NSObject
-(double)getPI;
-(double)multiply:(double) x and: (double) y;
@end
#import "calc.h"
@implementation calc
-(double)getPI
{
    return 3.14159265359;
}

-(double)multiply:(double) x and: (double) y
{
    return x * y;
}
@end

Now you call the methods different than other languages, too.

double pi = [myCalc getPI];
[myCalc add:1 and: pi;

Overriding the getter for the description property

Add the following method to your .m file. Inheriting NSObject already provides the method signature so nothing needs to be added to the .h file.

-(NSString *)description
{
    return @"Your custom description here";
}

Using NSString stringWithFormat

In many languages you can write a string with tokens inside it and just replace the token. You can do this in objective-c as well.

// cart.items is an integer
return [NSString stringWithFormat:@"You have @d items in your cart.", cart.items];
// cart.total is a double and since it is money, you only want to show
// two characters
return [NSString stringWithFormat:@"Total: %.2f", cart.Total];

Any object that is not a primitive, such as NSString, uses %@.

// account.username is an NSString
return [NSString stringWithFormat:@"Welcome %@", account.username];

Adding a UI Element (Label, TextBox, Button)

  1. You use the UI editor to add an the elements to the UI.
  2. Then you create a variable for each element.
  3. Then you link the field to the element in the xib.
#import <Foundation/Foundation.h>
@interface PersonViewController: UIViewController
{
    IBOutlet UILabel *nameLabel;
    IBOutlet UITextField *nameTextField;
    IBOutlet UIButton *submitNameButton;
}
@end
#import "PersonViewController.h"
@implementation PersonViewController
@end

Notice nothing is in the .m file. Of course, you could add these variables as properties and then you would an @synthesize call for these variables in the .m file.

Adding an event for clicking a button

This is pretty much the same as adding a method to an objective-c class. The only difference is you attach this method to a button in the xib.
Note: The button variable doesn’t really matter, it can by a property or just a member.

#import <Foundation/Foundation.h>
@interface PersonViewController: UIViewController
@property (nonatomic) IBOutlet UIButton *submitNameButton;
-(IBAction)buttonPressed:(id)sender;
@end
#import "PersonViewController.h"
@implementation PersonViewController
-(IBAction)buttonPressed:(id)sender
{
    // Button code here
}
@end

Wrap a ViewController in a UINavigationController

In AppDelegate.m, change the default application method to look as follows:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   
    ViewController *viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController: viewController];
    self.window.rootViewController = navCtrl;
    
    [self.window makeKeyAndVisible];
    return YES;
}

Add Buttons to the top bar (UIBar)

        // Setright bar button
        UIBarButtonItem * rightBarButton = [[UIBarButtonItem alloc]initWithTitle:@"Summary" style:UIBarButtonItemStyleBordered target:self action:@selector(summaryButton:)];
        self.navigationItem.rightBarButtonItem = rightBarButton;
        
        // Set left bar button
        UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc]initWithTitle:@"Map" style:UIBarButtonItemStyleBordered target:self action:@selector(mapButton:)];
        self.navigationItem.leftBarButtonItem = leftBarButton;

Launch a ViewController

If you have a UIViewController called MapViewController, you can launch it as follows.

    MapViewController *mapVC = [[MapViewController alloc] initWithNibName:@"MapViewController" bundle:nil];
    [[self navigationController] pushViewController:mapVC animated:YES];

Launch a ViewController and pass it data using a property

This passes a property called database into the SummaryViewController.

    SummaryViewController *summaryVC = [[SummaryViewController alloc] initWithNibName:@"SummaryViewController" bundle:nil];
    summaryVC.database = self.database;
    [[self navigationController] pushViewController:summaryVC animated:YES];

Other ways to pass it a property include:

  1. Using a custom init method such as initWithDatabase.
  2. Using a segue.

Get current date and time as string

NSString* currentTimeAsString()
{
    NSDate *date = [NSDate date];
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
    [dateFormat setDateFormat:@"d MMM YYYY, h:mm a"];
    NSString *dateString = [dateFormat stringFromDate:date];
    return dateString;
}

Using a UITabBarController

Change the application method in the AppDelegate.m file.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    UITabBarController *tabBarController = [[UITabBarController alloc] init];
    UIViewController *mileageView = [[MileageViewController alloc] init];
    UIViewController *mapView = [[MapViewController alloc] init];
    
    NSArray *controllers = [NSArray arrayWithObjects:mileageView, mapView, nil];
    [tabBarController setViewControllers:controllers];
    
    self.window.rootViewController = tabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}

Add image to TabBarItem

In the ViewController that is added as part of an array to the TabBarItem, override the iniWithNibName method as follows:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        UITabBarItem *tbi = [self tabBarItem];
        tbi.Title = @"Contacts";
        tbi.Image = [UIImage imageNamed:@"Contact-image.png"];
    }
    return self;
}

Map

Change the map view type.
-(IBAction) changeMap
{
    if (mapView.mapType == MKMapTypeStandard)
    {
        mapView.mapType = MKMapTypeSatellite;
    }
    else
    {
        mapView.mapType = MKMapTypeStandard;
    }
}

Update the user location on a map.

-(void)mapView:(MKMapView *)map didUpdateUserLocation:(MKUserLocation *)userLocation
{
    MKCoordinateRegion region;
    coord = userLocation.coordinate;
    // Start
    region = MKCoordinateRegionMakeWithDistance(coord, START_LATITUDE_SIZE, START_LONGITUDE_SIZE);
    
    [mapView setRegion:region animated:YES];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

TextBox resignFirstResponder

How to sort an NSArray

http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/sortedArrayHint

Categories (iOS version of Extension Methods in C#)

If an object is missing a method you think it should just have, such as NSDate returning the date in a specified format, you can simply create that method as follows and then use it anywhere you import the .h file.

#import <Foundation/Foundation.h>
@interface NSDate (DateExtender)
-(NSString *)getDateWithFormat:(NSString *)format;
@end
#import "DateExtender.h"
@implementation NSDate (DateExtender)
-(NSString *)getDateWithFormat:(NSString *)format
{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
    [dateFormat setDateFormat:format];
    return [dateFormat stringFromDate:self];
}
@end

Notice the class name is the same as the object you wish to extend: NSDate.
Notice there is a group name in paranthesis.

UITable

NSTimer

see Notice project.

Use a plist

see car project.

How to write your first C# Unit Test with Visual Studio?

Visual Studio makes Unit Testing easy by bundling a Unit Test framework into it.

Imagine you have a string extension method as shown below and you wanted to unit test it.

using System;

namespace ConsoleApplication1
{
    public static class StringExtensions
    {
        public static bool IsPrimaryColor(this string inString)
        {
            string[] primaryColors = { "Red", "Yellow", "Blue" };
            foreach (var color in primaryColors)
            {
                if (inString.Equals(color, StringComparison.CurrentCultureIgnoreCase))
                    return true;
            }
            return false;
        }
    }
}

Creating a Unit Test project to test this method is very easy.

Step 1 – Create a C# Unit Test Project

  1. In Visual Studio (assuming you already have a project open), click on the Solution and choose Add new project.
  2. Select Templates | Visual C# | Test from the menu on the left.
  3. Select Unit Test Project.
  4. Enter a name for the project.
    Note: Use a good name convention, such as naming the test project the same as the project it tests but with “Tests” at the end.  For example if you have a project called MyProject you would name your test project MyProjectTests. No, it isn’t rocket science. We like to keep it simple.
  5. Click OK.

Step 2 – Give your Unit Test project a reference to the project to test

  1. Right-click on References under the newly created Unit Test project and choose Add reference.
  2. Select Solution from the right.
  3. Add the project you plan to test as a reference.

Step 3 – Create your C# test class and first test method

  1. A test class was already created by default called UnitTest1.cs. Feel free to rename it to an appropriate name.
    Note: Use a good name convention, such as naming the test class the same as the class it tests but with “Tests” at the end.  For example if you have an object called MyObject you would name your test project MyObjectTests.
  2. Add a using statement to reference the namespace of the class you plan to test.
  3. Rename the first Test method. You can’t miss it. It has the [TestMethod] attribute.
    Note: Use a good name convention, such as naming the test method so clearly that you know what it is testing just by the name. For example, StringExtensionIsBlueAPrimaryColorTest().
  4. Add code to make your first test. It is recommended you create your method using the Arrange, Act, Assert pattern.
  5. Add additional test methods as needed.
    using ConsoleApplication1;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace StringExtensionTests
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void StringExtensionIsBlueAPrimaryColorTest()
            {
                // Arrange
                string color = "Blue";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsRedAPrimaryColorTest()
            {
                // Arrange
                string color = "Red";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsYellowAPrimaryColorTest()
            {
                // Arrange
                string color = "Yellow";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = true;
                Assert.AreEqual(expected, actual);
            }
    
            [TestMethod]
            public void StringExtensionIsBlackAPrimaryColorTest()
            {
                // Arrange
                string color = "Black";
    
                // Act
                bool actual = color.IsPrimaryColor();
    
                // Assert
                const bool expected = false;
                Assert.AreEqual(expected, actual);
            }
        }
    }
    

You have now created your first Unit Test. Go ahead and run it. You should be able to run it in Visual Studio starting with VS 2012. If you have an earlier version, you can run tests using other tools.

Thorough Unit Testing

OK. Now let’s think about what tests would be valid that we don’t have? Here are a few:

  • Case insensitive. All the following strings should return true: Red, red, rEd.
  • What if the string is blank? Null? Junk characters?

Now you write additional unit tests to test this method.

Note: It is too bad that Visual Studio’s MSTest doesn’t support Row tests. NUnit does support Row tests. With Row tests, the above Unit Test code would involve a single method that passing in multiple string values.

How to query a SQL database in C# using TableAdapters

Visual Studio has some great features to help you access the database and create objects for your database. You could manually create a connection string and manually create objects that represent the data in your database described here: How to query a SQL database in C#?. This article can show you how Visual Studio can do this for you.

So how is it done? By adding a Data Source.

Imagine you have a simple database for authentication with these tables:

User
- Id INT AUTOINCREMENT
- UserName VARCHAR(100)
- Password VARCHAR(MAX)
- Salt VARCHAR(MAX)

Person
- Id INT AUTOINCREMENT
- FirstName VARCHAR(255)
- LastName VARCHAR(255)
- Birthdate DATETIME
- UserId int FK to User.Id

Now imagine that you want to query these tables and use the data in your application.

Step 1 – Create a Visual Studio Project

  1. In visual studio create a new C# Console Application project.
  2. Once you have the project created, click on Project | Add New Data Source.
  3. Select Database and click Next.
  4. Select DataSet and click Next.
  5. Click New Connection and follow the wizard to connect to your database.
  6. Make sure that Yes, save the connection as is checked and give your saved connection a name and click Next.
  7. Click the checkbox next to Tables and click Finish.

This adds the following files to your project (the names might be slightly different on yours):

  • AuthDataSet.xsd
  • AuthDataSet.Designer.cs
  • AuthDataSet.xsc
  • AuthDataSet.xss

This code will add table adapters to your project. This basically does a lot of work for you and can save you a lot of potential development time.

Step 2 – Query a SQL Database using the Table Adapter

Now you can get the data from either of your tables with one line of code:

using System;
using System.Data;
using TableAdapterExample.AuthDataSetTableAdapters;

namespace TableAdapterExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Query the database (select * from Person) into a DataTable
            AuthDataSet.PersonDataTable table = new PersonTableAdapter().GetData();

            // Print out the table as proof.
            PrintDataTable(table);
        }

        /// How to print a DataTable
        private static void PrintDataTable(AuthDataSet.PersonDataTable table)
        {
            foreach (DataRow row in table.Rows)
            {
                foreach (DataColumn col in table.Columns)
                {
                    Console.Write(row[col].ToString().Trim() + " ");
                }
                Console.WriteLine();
            }
        }
    }
}

Hope that helps you.

ASP.NET, JavaScript, and HTML Element ID attributes

Today I had to fix some legacy code. It is ASP.NET code and it has both ASP.NET elements and ASP.NET Controls. The plan was to replace a large portion of code behind with JavaScript. The ASP.NET code needed to be a UserControl that could appear twice on the same page. This created some problems:

  1. ASP.NET creates some html controls but changes the id and the name attributes. While it is possible to run the web page and see what the attributes will be changed to and then use those strings statically in JavaScript, the JavaScript could easily break with slight changes to the ASP.NET code. This is not scalable or maintainable.
  2. ASP.NET does NOT rename the the id or the name attributes for normal HTML tags. First, that is a consistency issue. Second it is an issue using the same control multiple times. Third, if you want to get the value of a form element, doing so uses the name attribute and so each form element needs a separate name.

So lets explain the is problem with a real world scenario.

Lets say you have the following requirements:

  1. Create a UserControl, called PersonControl, that accepts person’s basic info: First name, Last name, and Birthdate.
  2. The form also has a button and it should only be enabled if all three fields are populated.
  3. The Birthdate should use JQuery’s DateTimePicker.
  4. The First name and Last name should be ASP.NET text boxes.

Now imagine the site already exists and you have to add this requirement:

  1. A web page should exist that has multiple PersonControls showing: for example: Employee, Emergency Contact.

The problem with ASP.NET, JavaScript, and HTML Element ID attributes

So let’s build this project using a single control and static id and name attributes and see how it works. Later we will see what we need to do to get this working with multiple PersonControls.

  1. Open Visual Studio and create a new ASP.NET Empty Web Application.
  2. Add JQuery and JQuery-UI. Do this as follows:
    1. Right-click on the project and choose Manage NuGet Packages.
    2. In the Manage NuGet Packages window, on the left, click Online.
    3. On the right, in the search field, type JQuery.
    4. Install JQuery and JQuery UI.
  3. Create new Web Form called PersonForm.
  4. Add the following into your PersonForm.aspx file:
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PersonForm.aspx.cs" Inherits="AspAndJavaScriptExample.PersonForm" %>
    
    <%@ Register Src="~/PersonControl.ascx" TagPrefix="uc1" TagName="PersonControl" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>ASP.NET, JavaScript, and HTML id Attributes</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <h2>Employee</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
            </div>
            <%--<div>
                <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
            </div>--%>
        </form>
    </body>
    </html>
    
  5. Create a new Web User Control called PersonControl.
  6. Add the following into your PersonControl.ascx file:
    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PersonControl.ascx.cs" Inherits="AspAndJavaScriptExample.PersonControl" %>
    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PersonControl.ascx.cs" Inherits="AspAndJavaScriptExample.PersonControl" %>
    <link href="Content/themes/base/minified/jquery.ui.datepicker.min.css" rel="stylesheet" />
    <script src="scripts/jquery-2.0.0.min.js"></script>
    <script src="scripts/jquery-ui-1.10.3.min.js"></script>
    <script src="scripts/ButtonManager.js"></script>
    <script>
        $(function () {
            $(".datepicker").datepicker();
        });
    </script>
    
    <div style="border: solid; padding: 2px">
        First name:
        <asp:TextBox ID="FirstName" runat="server"></asp:TextBox><br />
        Last name:
        <asp:TextBox ID="LastName" runat="server"></asp:TextBox><br />
        Birthdate:
        <input type="text" name="BirthDate" id="BirthDate" class="datepicker" /><br />
        <asp:Button ID="SubmitPerson" runat="server" Text="Submit" OnClick="SubmitPerson_Click" />
    </div>
    
  7. Add the following button SubmitPerson_Click method into your PersonControl.ascx file:
            protected void SubmitPerson_Click(object sender, EventArgs e)
            {   // Put break point here            
                var firstName = FirstName.Text;
                var laststName = LastName.Text;
                var birthdate = Request.Form["Birthdate"];
            }
    
  8. Now add this ButtonManager.js file.
    jQuery(document).ready(function () { 
        $("#PersonControlEmployee_FirstName").bind("propertychange keyup input paste", setButtonState);
        $("#PersonControlEmployee_LastName").bind("propertychange keyup input paste", setButtonState);
        $("#BirthDate").change(setButtonState);
        setButtonState();
    });
    
    var setButtonState = function () {
        if (!areValuesPopulated())
            $("#PersonControlEmployee_SubmitPerson").attr("disabled", "disabled");
        else
            $("#PersonControlEmployee_SubmitPerson").removeAttr("disabled");
    }
    
    var areValuesPopulated = function () {
        return $("#PersonControlEmployee_FirstName").val() != ""
             && $("#PersonControlEmployee_LastName").val() != ""
             && $("#BirthDate").datepicker().val() != "";
    }
    
  9. Now run the project and look at the source code of the html. It looks as follows:
    
    
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head><title>
    	ASP.NET, JavaScript, and HTML id Attributes
    </title></head>
    <body>
        <form method="post" action="PersonForm.aspx" id="form1">
    <div class="aspNetHidden">
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="nkizDAjcAtd96A9EOpli0xdG3n6zTXVaM/5t2fmcAI5+LPQ6OzzIV2wUpisxoUTMFxIKkUwKDY4Xk36/NouRsiE81gq5z3Ch/tz3DlxJW9g=" />
    </div>
    
    <div class="aspNetHidden">
    
    	<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="XCB0fxwKvdqEXpUBaICUtf6EzkAvBeahq0bywZekyukCuzvGVagqOnVHUWFHF2Cycd2xkg/UhNh/B3qNqabkBI+Flj52GkM3p6SF5eL/M4SnnfwmFBjWVOaTZ+IlwMvkR1bGuMxomyeJJ5HaU1FXWSYDYHVtgM9tdsVi31EireM=" />
    </div>
            <div>
                <h2>Employee</h2>
                
    <link href="Content/themes/base/minified/jquery.ui.datepicker.min.css" rel="stylesheet" />
    <script src="scripts/jquery-2.0.0.min.js"></script>
    <script src="scripts/jquery-ui-1.10.3.min.js"></script>
    <script src="scripts/ButtonManager.js"></script>
    <script>
        $(function () {
            $(".datepicker").datepicker();
        });
    </script>
    
    <div style="border: solid; padding: 2px">
        First name:
        <input name="PersonControlEmployee$FirstName" type="text" id="PersonControlEmployee_FirstName" /><br />
        Last name:
        <input name="PersonControlEmployee$LastName" type="text" id="PersonControlEmployee_LastName" /><br />
        Birthdate:
        <input type="text" name="BirthDate" id="BirthDate" class="datepicker" /><br />
        <input type="submit" name="PersonControlEmployee$SubmitPerson" value="Submit" id="PersonControlEmployee_SubmitPerson" />
    </div>
    
            </div>
            
        </form>
    </body>
    </html>
    

Problems

  1. Notice the id and name attributes on the tags. The ASP.NET controls have been altered by ASP.NET with a prefix. This is not the problem. This is good. If the control is used multiple times, then this keeps the id and name attributes unique and they are supposed to be unique. However, the problem is, if the id is changed in this line . . .
    <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
    

    . . . then id and name attributes in the child control will change. Since we are using those values statically in the ManageButton.js, any such change also breaks in the javascript. Also, we aren’t using a master page, but if you decided to add a master page, that add an additional prefix, which would create different id and name attributes, again causing the javascript to break. In fact, any such nesting change will change the id and name attributes breaking the javascript.

  2. The control that is not an ASP.NET control, the JQuery datepicker control, did not have the same modifications made to the Birthdate. So this tag won’t work if the control is used multiple times.

Do you want to see the problem?

Update your form in PersonForm.aspx to include multiple controls.

    <form id="form1" runat="server">
        <div>
            <h2>Employee</h2>
            <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
        </div>
        <div>
            <h2>Emergency Contact</h2>
            <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
        </div>
    </form>

Now give it try. See the problems? Ok. So now you have a simulation of the problematic code that I faced today.

Solution to ASP.NET, JavaScript, and HTML Element ID attributes

So we are going to fix this in parts. We are going to use a variable in the ASP.NET control called ClientID, that is basically the prefix used.

  1. Fix html elements to use the same prefix as the ASP.NET controls
  2. Fix the javascript to receive the ClientID as a parameter
  3. Fix the datepicker attributes

    First, let’s fix the ASP.NET and HTML so that all the id and name attributes are consistently changed.

    Change the datepicker line and add some code so it will have the same prefix as ASP.NET created html controls.

    <input type="text" name="<%=ClientID%>$BirthDate" id="<%=ClientID%>_BirthDate" class="datepicker" /><br />
    

    Pass the prefix into the JavaScript

    1. In the PersonControl.ascx file, add a little snippet of JavaScript code to pass the ClientID into the JavaScript files.
      <script>
          $(function () {
              $(".datepicker").datepicker();
          });
          jQuery(document).ready(function () {
              startManagingButton("<%=ClientID%>");
          });
      </script>
      
    2. Now update your JavaScript file to use that ClientID as the prefix. Notice, this is used in the events. I created a simple buildId method that I use throughout now.
      var startManagingButton = function (inIdPrefix) {
          $(buildId(inIdPrefix, "_FirstName")).bind("propertychange keyup input paste", inIdPrefix, setButtonState);
          $(buildId(inIdPrefix, "_LastName")).bind("propertychange keyup input paste", inIdPrefix, setButtonState);
          $(buildId(inIdPrefix, "_BirthDate")).change(inIdPrefix, setButtonState);
          setButtonState(inIdPrefix);
      }
      
      var setButtonState = function (inIdPrefix) {
          if (inIdPrefix.data)
              inIdPrefix = inIdPrefix.data;
          
          if ($(buildId(inIdPrefix, "_FirstName")).val() == "" || $(buildId(inIdPrefix, "_LastName")).val() == "" || $(buildId(inIdPrefix, "_BirthDate")).val() == "")
              $(buildId(inIdPrefix, "_SubmitPerson")).attr("disabled", "disabled");
          else
              $(buildId(inIdPrefix, "_SubmitPerson")).removeAttr("disabled");
      };
      
      var buildId = function (inIdPrefix, idSuffix) {
          return "#" + inIdPrefix + idSuffix;
      };
      

      Now no matter how you update or move this web page, the Id values always work.

    Use the ClientID in ASP.NET SubmitPerson_Click method

    Update the code to look as follows:

        protected void SubmitPerson_Click(object sender, EventArgs e)
        {   // Put break point here            
            var firstName = FirstName.Text;
            var laststName = LastName.Text;
            var birthdate = Request.Form[ClientID + "$Birthdate"];
        }
    

    Using the PersonControl multiple times

    Now everything should be working and you should be able to include as many instances of your control in your web page as you want.

    Update your form in PersonForm.aspx to include many of these controls.

        <form id="form1" runat="server">
            <div>
                <h2>Employee</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmployee" />
            </div>
            <div>
                <h2>Spouse</h2>
                <uc1:PersonControl runat="server" ID="PersonControlSpouse" />
            </div>
            <div>
                <h2>Emergency Contact</h2>
                <uc1:PersonControl runat="server" ID="PersonControlEmergencyContact" />
            </div>
        </form>
    

    Now give it try. All instances of the PersonControl are now working. The dynamic id and name attributes are not a problem as we are handling them; in fact, they are part of the ultimate solution to make the control reusable.

    Conclusion

    ASP.NET, JavaScript, and HTML Element ID attributes can all be used to work together to make a nice cohesive application.

    If you have a better solution, please post a comment and let me know.

    Downloads

    Here is the project in both states:

    AspAndJavaScriptExample-problematic.zip

    AspAndJavaScriptExample-working.zip

    Bugs

    Now the only bug I can find is on clicking submit the JQuery datepicker field is cleared. I’ll try to fix that and post the solution in another post.

How to create an excel spreadsheet with C#?

I needed to create an Excel spread sheet in C# and I didn’t want to reinvent the wheel.

I found this awesome project: https://closedxml.codeplex.com

I already had a DataTable that I wanted to export in ASP.NET to an Excel file and download. I created an extension method for the DataTable.

    public static class CloseXMLHelper
    {
        public static XLWorkbook ToExcel(this DataTable inDataTable)
        {
            var wb = new XLWorkbook();
            var dataTable = inDataTable;

            // Add a DataTable as a worksheet
            wb.Worksheets.Add(dataTable);
            return wb;
        }
    }

Then I just followed the documentation on the project for allowing a user to download the excel file. I already had the myDataTable variable in the below snippet. If you are wondering how to create a DataTable from a database, see this post: How to query a SQL database in C#?

    var httpResponse = Response;
    httpResponse.Clear();
    httpResponse.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    httpResponse.AddHeader("content-disposition", "attachment;filename=\"HelloWorld.xlsx\"");

    // Flush the workbook to the Response.OutputStream
    using (var memoryStream = new MemoryStream())
    {
        dataset.Tables[0].ToExcel().SaveAs(memoryStream);
        memoryStream.WriteTo(httpResponse.OutputStream);
        memoryStream.Close();
    }

    httpResponse.End();

It doesn’t get much more simple than this.

How to execute a sql statement with a parameter in SQL Management Studio?

Today I got asked how to execute a parameterized SQL query in SQL Management Studio.

You can do it two ways:

Method 1 – Use SP_EXECUTESQL stored procedure to execute parameterized SQL

DECLARE @query NVARCHAR(MAX) = N'SELECT * FROM customer WHERE CustomerId = @id'
DECLARE @params NVARCHAR(MAX) = N'@id int';

EXEC SP_EXECUTESQL @query, @params, @id = 3;

If you need to do multiple parameters, it is pretty much the same syntax.

DECLARE @query NVARCHAR(MAX) = N'SELECT * FROM customer WHERE CustomerId IN (@id1, @id2)'
DECLARE @params NVARCHAR(MAX) = N'@id1 int, @id2 int';

EXEC SP_EXECUTESQL @query, @params, @id1 = 3, @id2 = 4;

Method 2 – DECLARE Variables to execute parameterized SQL

DECLARE @id INT = 3;
SELECT * FROM customer WHERE CustomerId = @id;

If you need to do multiple parameters, just declare another variable.

DECLARE @id1 INT = 3;
DECLARE @id2 INT = 4;
SELECT * FROM customer WHERE CustomerId IN (@id1, @id2);

An HTML5 3 column layout example in ASP.NET

A while back I posted about an html5 three column layout. Here is the same layout, only this post has built the web site using ASP.NET and it includes a Visual Studio project.

The _Layout.cshtml file looks like this:

@RenderPage("~/Layout/_Header.cshtml")
@RenderPage("~/Layout/_Nav.cshtml")
<div id="main">
   <article id="main-article">@RenderBody()</article>
    @RenderPage("~/Layout/_LeftAside.cshtml")
    @RenderPage("~/Layout/_RightAside.cshtml")
</div>
@RenderPage("~/Layout/_Footer.cshtml")

Then of course, the HTLM5 layout is in the header, asides, article, and footer. And even though the Article is placed before the asides, the asides can be either on the left or the right.

Download it here: HTLM5_ASPNET_ThreeColumnLayoutExample.zip

How to add a “Start” shortcut in Windows 8 (or Where is start in windows 8)

Too many people are paying for software to provide a complete return the windows Start pop-up menu. Well, Start is still there in Windows 8, it is just a little different. It is not a pop-up menu. It is hidden by default and only shows when you move your cursor to the bottom left corner.

I think many people would be happy if they simply had a shortcut to the Apps screen, which is equivalent to All Programs.

Well, lets create a shortcut and put in on the task bar. Follow these steps.

Note: Alternately, you can download and extract the zip file from here: AllPrograms.zip

Step 1 – Create the Windows 8 Apps Shortcut

  1. Right-click on the Desktop and click New | Shortcut.
  2. Where it prompts you to “Type the location of the item” enter this:
    %windir%\explorer.exe shell:::{2559a1f8-21d7-11d4-bdaf-00c04f60b9f0}
  3. Click Next.
  4. Name the shortcut what ever you want. “Start” or “All Programs” or whatever, it really doesn’t matter.
  5. Click Finish.

Step 2 – Change the Icon for the Windows 8 Apps Shortcut

You may want to change the icon too.

  1. Right-click on your newly created shortcut and choose Properties.
  2. Click Change Icon…
  3. Select a different icon from the list or download your own .ico file and use it.

Step 3 – Drag the Windows 8 Apps Shortcut to the task bar

  1. Right-click on your newly created shortcut and choose Pin to taskbar.
  2. Now if you want this icon all the way on the left, click and drag it there.

Windows 8 Negativity Debunked!

I love BSD and Linux and as an Open Source guy since 2001, many people expect me to hate Microsoft.  Well, guess what? I don’t hate Microsoft at all. I love the technology. I love most technology. So unlike many, I am not religious about my operating system. I am completely happy to spin up a Windows Server where it makes sense and a FreeBSD/Linux server where that makes sense. I am even known to run a PC-BSD desktop and avoid paying for a commercial operating system.

Currently for my desktop, I run Windows 8.

I really, truly enjoy running Windows 8. I am running it on both my laptop and my desktop. I love the Metro interface and find it works quite well for me. I use it to easily find and run my applications, just as I used Start in Windows 7. I love having both a Metro and a Desktop interface as well as having both Metro and Desktop apps.

I hear general complaints on the web.

“I miss the Start bar.”
“It’s harder to launch my apps.”
“I hate the metro interface.”

Really. Why? It is actually easier to use.

“Start is missing.” – Debunked!

Is Start really missing? No. It is there, just it has to pop up. And guess what? It even says “Start”.

Start Icon

The difference between the Start button in previous versions and the Start button in Windows 8 is not a long list.

  1. You don’t see a start button/icon until you move to the cursor all the way to the bottom left corner. However, the image that pops up does say “Start”.
  2. The screen doesn’t pop up over your current desktop view, instead it opens using the full screen.
  3. It shows both desktop apps and metro apps.

Well, are these three differences that big of a deal. Of course not. The first two are not missing features, just a different way to view things. The last one is actually a feature add.

Unfortunately, there are haters out there. Those who are religious about their operating system. Each operating system has those who are nut-job religious. Yes, I’ve seen nut-jobs for Microsoft, Apple OSX and iOS, BSD, Linux, Unix, Android. Heck, I’ve even seen nut-jobs for just one flavor of Linux (Red Hat, Debian, Ubuntu, Fedora, Slackware, Symbios, etc…). So naturally when nut jobs see a little blood in the water they attack.

Can improvements be made? Yes. I see no reason that Start has to be hidden by default. Historically, hiding or showing things has been an option. It is really the lack of the option that is all Microsoft missed. If so, that is not a big deal at all.

“It’s harder to launch my apps.” – Debunked

Windows 8 is the operating system for launching Windows applications. Historically, you have been able to launch apps in the following manner:

  1. Directly click the executable.
  2. Click a shortcut you can place anywhere (folder or desktop or Start bar)
  3. Click Start then move the cursor to All Programs, move the cursor again, and then scroll through All Apps.
  4. In Windows 7, they added the feature to click Start, just type in the first part of the program and the search would find the application for you.

Has anything changed in Windows 8. No, it hasn’t. I can still do all three with Windows 8.  What is different.

  1. Clicking Start is displayed full-screen.
  2. Getting to All Apps doesn’t require a lot of scrolling, instead it is Click Start. Right-click and choose All Apps.

These again are not feature losses but simply different views.

Go ahead and click Start, type in “No” and see that Notepad immediately shows up.

Go ahead and click Start, type in “Cont” and see that Control Panel immediately shows up.

It functions the same as Windows 7.

Is there room

“I hate the metro interface.” – Not debunked!

So let’s start with the fact that generic statements like this are just opinion and too general to really do anything about. What do you hate? Do you hate the full screen? Do you hate the way Metro Apps are opened? Lets take this to a more granular level.

“I hate seeing the full screen when I click start.” – Just opinion.

Well, this is opinion. No one can debunk or not debunk this. Personally, I don’t care either way. It works well for me, so I have no complaints.

Is there room for improvement? Yes.

I would like an option to see this in full-screen or in a window. Then those that hate it opening as full screen don’t have to have it open as full screen.

I would also like to be able to set whether to see the Start screen or the Apps screen is displayed when I click Start. However, this feature is easy to add using a shortcut. I will link to a post on how to create a shortcut to the Apps screen. You could even name the shortcut Start and put in on the bottom left.

“I hate that opening a metro app takes the whole screen”  – Not Debunked a real problem but fixable

Yes, metro apps take up the whole screen. Worse, some things, like pdf files, open in a metro app by default. I had to install Acrobat Reader to make this go away, but only for opening pdf files. Even worse is trying to figure out how to close a metro app for the first time.

This is really the only thing that bothers me about Windows 8. When I launch a metro app, it opens full screen and I have no option to make it just a window. The Metro app experience is not really that great for a desktop/laptop.

I want all my windows to be re-sizable and I want to have multiple windows up at once. So should Metro and Desktop modes be completely separated. Of course not. There is only one feature that is annoying. The fact that metro apps open full screen. Simply add an option to open metro apps in a window and now everything is fixed.

This is fixable. I may write a post on how to resolve this later. If I do, I will link to the solution here.

Conclusion

There was only one real problem, in that metro apps open full screen and you can’t run multiple apps at once. The rest are just options people want. If Microsoft makes these changes, the major complaints are resolved:

  1. Allow an option to hide or display the Start icon.
  2. Allow Start and Apps metro screens to be opened in windows.
  3. Allow Start to be configurable to either open Start or Apps metro screens.
  4. Allow a setting to make metro apps to be opened in windows and make it the default setting on desktops and laptops.

Wow! A brand new interface and really four features resolve the world’s major complaints, most of which are not really that big of complaints in the first place.

We haven’t yet discussed the new features in Windows 8 yet, such as Hyper-V, which saves me a lot of money on a separate VMWare Workstation license.

My Recommendation

Take another look at Windows 8!