Author Archive

Optimizing for the iPhone “Retina Display” and Other High Resolution Devices

Optimizing for the iPhone “Retina Display” and Other High Resolution Devices

The iPhone 4 and new iPhone 4s come featured with Apple’s “Retina Display”. This is a 3.5 inch screen with a resolution of 960×640 at 326 pixel per inch. Compared to its predecessor, the iPhone 3GS, this display is a very significant improvement. Once you get used to the Retina Display older devices will no longer cut it. The pixelation of graphics with lower ppi devices stick out like a sore thumb leaving high resolution users dissatisfied. Here we’ll show you how to target these devices and optimize to bring users the best quality in web graphics.

Below are identical logos being viewed on the iPhone 4 with Retina Display. It’s quite obvious which of the two below has been optimized for the high resolution devices. As mobile application and websites become more and more common using high resolution graphics it is something developers today need to consider when developing applications and websites.

 

Identical logos being viewed on the iPhone 4 with Retina Display.

So how do we go about targeting a high ppi device?

When developing an application much of the work is done for us. Create and save two different versions of each graphic we want to optimize. One of them should be saved at 163ppi (iPhone 3GS) and the other should be twice the size and saved at 326 ppi. Applying the suffix “@2x” in the image title of the high ppi image will trigger iOS to use that particular image when a device with Retina Display is being used. An example of this naming convention would be “myimage.jpg” and “myimage@2x.jpg”.

Mobile Safari does not automatically recognize the “@2x” suffix so we have to target the mobile devices with high dpi and query an alternate stylesheet. The following code will do just that:

<link rel=”stylesheet” type=”text/css” media=”only screen and (-webkit-min-device-pixel-ratio: 2)” href=”retinaDisplay.css” />

If you had a 12×12 icon on your webpage in this stylesheet you would load the 24×24 version of the icon and specify its height and width to be 12×12. It is also possible to do this using just your image tag. For example:

<img src=”myImage24x24” width=”12” height=”12” />

The iPhone uses the name “Retina Display” for its new display because the classification of the images displayed by the device is so high the human eye is unable to differentiate its pixels. Beyond the percentage of resemblance of the human eye and the “Retinal Display”, the reality is that nobody has achieved anything closer to human vision prior to this. Apple has come up with an approach that has changed the way we see images on the iPhone.

 

Interested in Mobile Development? Contact Unidev

Building a List of Random Results Based on a Weighted Sort Index in T-SQL

I had an interesting requirement for a project recently. I needed to randomly sort database records that already have a sort preference number. That is to say, each record with the same sort number needs to be randomized in a group with others of the same number. Then those are returned as a group in an order based on the original sort order compared to a group of other sort numbers. Using this data for example:

ID

Sort Pref

1

10

2

10

3

200

4

200

5

200

6

333

7

333

 

I always want 1 and 2 to come before 3, 4, or 5 and for those before 6 and 7. But 1 and 2 could be in any order just like 3, 4, and 5 and so on.  So either of these could be valid results: 1,2,5,3,4,7,6 or 2,1,4,3,5,6,7

I originally just returned them in an order of the SortPref padded with zeroes and appended with a NewID() guid.  For example:

SELECT Right('0000000000' + Convert(varchar(10), SortPref), 10)
+ Convert(varchar(50), (NewID())) as SortPref
000000010EDE455E6-ED80-4752-9A26-3321226EDAA9
     000000010B6D63097-9CBE-4D88-B43F-6CDEA460A028
     000000200D02F7DDB-5245-42EF-A148-F8F34836DB1F

etc…

This worked, but one caveat is that I wanted the random order to be consistent, at least for a time. But every subsequent query returned a completely new order. For example, showing 3 per page, I could see 1,2,5. Then going to page 2 to see three more, I could see 3,5,7. That second batch was not the next three from the previous query. It is items 4-6 of a brand new query (notice 5 is in both). Then going back to page 1 will show 3 completely new random results in a different order, possibly 2, 1, 4.

Using the SQL Rand()function seemed like it was going to be great because passing it the same seed each time will produce the same “random” number and also consistent  numbers each time thereafter. Each time the following SQL is executed it will return the same 3 numbers.

SELECT Rand(18), Rand(), Rand()

So I ditched the padding and guid and wanted to combine the existing sort preference number with a random decimal. I needed a new number for each row returned so I put the random number generating code right in the SELECT statement. This seems likely to work, but it does not. Rand() works similar to GetDate() in that the current datetime is fetched once and returned for every row. So I was getting the same suffix for each row.

SELECT SortPref + Rand (Cast (NewID () AS VarBinary)) AS SortPref

Since I need to get a new random number for each row, I instead made an update statement to put that result into a new integer column. This got me what I wanted and then I just sort by that column.

 

UPDATE List SET SortPref_RAND = SortPref + Rand( Cast( NewID() AS VarBinary ))
SELECT SortPref_RAND ORDER BY SortPref_RAND 

 

ID

Sort Pref

Sort Pref with a Random Decimal

2

10

10.0169181358024

1

10

10.8794841987447

5

200

200.296572565734

4

200

200.476788464425

3

200

200.579782703862

6

333

333.464425198756

7

333

333.782769181334

 

I chose to run this update daily so that a user’s results will not change even from the morning to evening. I keep track of the last date the random column was updated and if it is yesterday (so the first time a search is performed after midnight) then the update is performed again.

Selecting An Old Value While Binding a DropDownList

I had a usual instance where a DropDownList was bound to a table in a database. However, that list of data could change in the database without regard to those values having been previously stored (as text, not IDs, unfortunately) in another table. Meaning that when the DropDownList would now be loaded with the newly updated data, the previously selected value would not have a corresponding choice in the drop down anymore.

The DropDownList doesn’t take too kindly to this and gives an ArgumentOutOfRangeException error. But I needed that old value as a possible choice in the dropdown still, as well as the new choices.

The problem was that I needed to get the saved value from the database (which failed to be the initial SelectedValue). So I just stored it in the ToolTip for the DropDownList, then I could retrieve it and update it from anywhere.

Note: Be sure to use OnDataBinding not OnDataBound to add the new item.

<asp:DropDownList ID=”HotelNameDropDown” runat=”Server” DataSourceID=”ObjectDataSource1″

SelectedValue=’<%# Bind(“HotelName”) %> AppendDataBoundItems=”true”

OnDataBinding=”HotelNameDropDown_OnDataBinding” ToolTip=’<%# Bind(“HotelName”) %>

OnSelectedIndexChanged=”HotelNameDropDown_OnSelectedIndexChanged”

DataTextField=”HotelName” DataValueField=”HotelName” />

Depending on when you postback, you might also need to update the ToolTip when the user changes the DropDownList.

protected void HotelNameDropDown_OnSelectedIndexChanged(object sender, EventArgs e)

{

// Set the tooltip to the selected value onchange, becuase we will use the tooltip below

DropDownList ddl = (DropDownList)sender;

ddl.ToolTip = ddl.SelectedValue;

}

Here I try to bind the DropDownList with the data, if this fails then it creates a new ListItem at the top of the list with a name and value of what we had stored in the ToolTip from the .aspx page.

protected void HotelNameDropDown_OnDataBinding(object sender, EventArgs e)

{

DropDownList ddl = (DropDownList)sender;

ddl.DataBinding -= new EventHandler(HotelNameDropDown_OnDataBinding);

try

{

ddl.AppendDataBoundItems = false;

ddl.DataBind();

ddl.SelectedValue = ddl.ToolTip;

}

catch(ArgumentOutOfRangeException)

{

ddl.Items.Clear();

ddl.AppendDataBoundItems = true;

ListItem li = new ListItem(ddl.ToolTip, ddl.ToolTip);

li.Selected = true;

ddl.Items.Insert(0, li);

}

}

More info about this topic can be found here:

http://www.jeffgaroutte.net/post/2008/07/09/The-DropDownList2c-the-DataBind-and-the-Missing-Value.aspx

Dynamically Loading External Controls from a DropDownList

Displaying a specific web user control (.ascx) from a dropdown selection is a fairly straightforward process.

Create an asp:DropDownList with OnSelectedIndexChanged set to a function. This function will load a user control file based on the selected value of the dropdown. Also, create an asp:PlaceHolder where the control will be placed.

 

       <asp:DropDownList ID=”ddDataTables” runat=”server” AutoPostBack=”true”

OnSelectedIndexChanged=”ddDataTables_Changed” >

         <asp:ListItem Text=”" Value=”"></asp:ListItem>

         <asp:ListItem Text=”More Options” Value=”more_options”></asp:ListItem>

         <asp:ListItem Text=”Address” Value=”address”></asp:ListItem>

 

    <asp:PlaceHolder ID=”phDataTable” EnableViewState=”false” runat=”server” />  

 

And the code behind file looks for a file which is named the same as the selected value (e.g. address.ascx), then adds it to the place holder in the aspx file.

 

    protected void ddDataTables_Changed(object sender, EventArgs e)

    {

        LoadUserControl(ddDataTables.SelectedValue);

    }

   

    protected void LoadUserControl(string strSelectedTable)

    {

        phDataTable.Controls.Clear();

 

        if (strSelectedTable != “”)

        {

            UserControl ucDataTable = (UserControl)LoadControl(strSelectedTable + “.ascx”);

            phDataTable.Controls.Add(ucDataTable);

        }

    }

 

That’s it. A simple way to keep functionality separated in web user controls but be able to still pull them in cleanly when desired.

 

Triggering a Specific GridView Row Command When Page Loads

I have an asp.net page with a gridview and each row uses a TemplateField to make a LinkButton to select the row. In my case, the action of clicking the text link triggers a FormView to appear in order to edit the data.

 

I needed a way to open the editing form automatically for the first item in the gridview when the page loads. After using combinations of different .NET page events (Page_Render(), Page_Unload(), etc.), I found myself going around and around because I was never at the right point in the execution order for getting the data bound , knowing the correct CommandArgument and having access to all the data in the row at the same time. I was setting session variables and checking IsPostBack and it was becoming more complicated than it seemed like it needed to be.

 

It was time to rethink the whole issue. I ended up writing 1 line of javascript with a little prep C# code which finds the correct LinkButton, transforms its .NET generated ID into something useful, and then stores it for the javascript to use. The javascript executes a postback after the page loads so it mimics a user clicking on the “Edit” link, just like I wanted.

 

The code for the edit link as a column in my gridview:

 

<asp:TemplateField ShowHeader=”False”>

<ItemTemplate>

<asp:LinkButton ID=”LinkButtonSelect” runat=”server” CausesValidation=”False”

                CommandName=”Select” Text=”EDIT”

    CommandArgument=’<%# Bind(“ID”)%>‘>

</asp:LinkButton>

</ItemTemplate>

</asp:TemplateField>

 

In my C# code I check if there are any rows in my grid before I attempt to postback on anything and I’m choosing row 0 because I want the first row. The parameter for __doPostBack needs to have dollar signs instead of underscores like the ID has, so I replace them accordingly.

 

At the bottom of my.aspx page I have this javascript code (which could also be added into the onload event):

 

<script type=”text/javascript”>

 

<%

    // Get and format the the ID of the Edit link in the first row

    if (GridView1.Rows.Count > 0)

    {

        LinkButton lnkEdit = (LinkButton)GridView1.Rows[0].FindControl(“LinkButtonSelect”);

        string strEditID = lnkEdit.ClientID.ToString().Replace(“_”,“$”);

%>

         // trigger a postback like someone clicked “Edit”

         __doPostBack(‘<%= strEditID %>’, );

 

<%

    }

%>

 

</script>

 

So in the end, the javascript line has the same value as the href attribute that is generated for the LinkButton. View the source code of your page and check it out!

Display a Nested List Inside Another Repeater

A simple way to display a list of data is to use an asp:Repeater. If the data also needs to show a nested list of related data for each main item, one can place another Repeater inside the first. In the code behind, the queries used for each Repeater can be linked in a dataset as a parent-child relationship via a Data Relation.

In the example below we make the multiple queries in only one SQL command statement, then link the result tables together by making a new DataRelation. The link uses key and foreign key ID columns from each result set.

This C# example shows how you can have a list of phone numbers as an area inside a larger list of contacts.

             In the Page_Load function…
             …

        // Create and fill a DataSet
SqlDataAdapter myCommand = new SqlDataAdapter(

            "SELECT DISTINCT MemberID, Address, FirstName, LastName " +
            " FROM MemberNames M; " +

            "SELECT MemID, phonetype, Number " +
            " FROM MemberNames M " +
            " INNER JOIN Phone P ON M.MemberID = P.MemID;" +
             , myConnection);

         DataSet ds = new DataSet();
        myCommand.Fill(ds);

         // Relate the two tables from the query together
        ds.Relations.Add(new DataRelation("MemberID_Phone", ds.Tables[0].Columns["MemberID"], ds.Tables[1].Columns["MemID"]));

        // Bind the outer Repeater to the DataSet.
        rptMember.DataSource = ds.Tables[0];
        rptMember.DataBind();

 When we bind the data for each item in the outer Repeater, we will create a child view using the relation we linked previously.

     protected void rptMember_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        DataRowView drv = e.Item.DataItem as DataRowView;
         Repeater rptPhone = e.Item.FindControl("rptPhone") as Repeater;

        rptPhone.DataSource = drv.CreateChildView("MemberID_Phone");
        rptPhone.DataBind();
    }

 This snippet from the .aspx files shows the nested repeaters.

<asp:Repeater id="rptMember" OnItemDataBound="rptMember_ItemDataBound" runat="server">

         <ItemTemplate>

          <!– Tags to display the bound data (name, address, etc.) –>  

          <!– Make a repeater for all phone numbers for each person –>

            <asp:Repeater id="rptPhone" runat="server">
              <ItemTemplate>
                <%# DataBinder.Eval(Container.DataItem, "PhoneType")%>:
                <%# DataBinder.Eval(Container.DataItem, "Number")%>

              </ItemTemplate>
            </asp:Repeater>

            …

 To sum it all up, we implemented several technical elements here. 

  • Nested Repeaters
  • Using a multi-result query
  • Using DataSet Relations

 Our example displays a list of Contacts with a sub-list for multiple phone numbers.

Importing Mixed ZIP Codes into SQL Server from Excel

I had a spreadsheet with tens of thousands of mailing addresses. One of the columns was  the ZIP code for each address row.  Some of those ZIP codes were in the ZIP + 4 format (12345-6789) and others were not.  Those others were 3, 4 or 5 digit numbers.  When the data was put into the spreadsheet, Excel removed the leading zeroes from some ZIP codes (like “00345” truncated to “345”).

I used the Import functionality in SQL Server Management Studio 2005 to put the data from the Excel spreadsheet into a table.  Without modifying the spreadsheet data the import would place a NULL into each row that had a 3,4 or 5 digit ZIP code, while keeping the ZIP + 4 codes correctly.

To get both “5-Digit” and “Zip Plus Four” ZIP codes into the same database column I needed to make Excel see them as text. To do this I made a new column next to my ZIP Codes with this style of formula:                =TEXT(B2,”00000″)

zipcode-excel-as-text

This causes the data to have at least 5 digits and leading zeroes if less than five  digits. Next I copied this new column and then used “Paste Special” with the “Values” option to replace my original ZIP code column. Saving the spreadsheet and executing a SQL Server import of the XLS file, all ZIP codes were then correct.

zipcode-excel-paste-special

I also found that using the “Format Cells” functionality with the Special “Zip Code” setting only changes how the data appears. It does not change the underlying data. For example “345” shows as “00345” but if you look at the actual data, it remains unchanged. So just doing Excel formating did not work when importing in to a SQL Server database.

zipcode-excel-formatted

Using A Data Container Column as an Inline IF Condition

I find myself using .net data containers in many web applications.  Binding controls such as asp:Repeater and asp:DataList to data sources can make displaying your data more manageable.  In a few of those instances I need to have some of the data display in a little different manner depending on that particular info.

For example, a “sold” image could be shown if the status of a data item warrants it.  If the status is anything else no extra HTML is rendered.

<%# (DataBinder.Eval(Container.DataItem, "Status").ToString() == "Sold") ?
<img src='/images/sold.gif' />" : "" %>

Instead of making a server-side control in my .aspx page then having my code behind find it in some sort of databound function, I find it cleaner to use an inline C# IF statement for simple display changes such as these.

In the sample code below, we are making an anchor link. The data in the “Type” column from the database describes if the data is a URL or an email address.  Our inline IF statement has this structure:

If the Type equals “Website” then add nothing to the data.  Otherwise, the data is an email address, so make a “mailto:” link out if it.

<asp:Repeater id="rptAddress" runat="server">
<ItemTemplate>

<a href="<%# (DataBinder.Eval(Container.DataItem, "Type").ToString() == "Website") ?
 "" : "mailto:" %>   <%# DataBinder.Eval(Container.DataItem, "Address")%>" >
<%# DataBinder.Eval(Container.DataItem, "Address")%>
</a>
</ItemTemplate>
</asp:Repeater>
Just remember, the C# syntax for an inline If uses the question mark and a colon:
<% (condition) ? "true" : "false" %>

Saving Web Contact Info to a Downloadable Spreadsheet

Usually a website owner has the data from their contact forms emailed to them.  But sometimes it can be useful for the site to automatically add that info to an ongoing list of contacts.  One way that most people like to be able to see and sort such data is in a spreadsheet.  It is quite easy to make a “fake” spreadsheet using an html table that Excel will open like any other .xls file.

 

Here are the basic steps:

  • Create and save a “spreadsheet” which defines the header row
  • Upon each contact form submittal, write an html row to that file 

Read the rest of this entry »

sql transactions in c# .net

I recently needed to update an existing C# solution of multiple projects to add transactions around two different data updates.  I wanted to have this pattern for each one:

 

  • Start transaction
  • Delete all existing data
  • Insert all new data
  • Commit transaction

Read the rest of this entry »