Using anonymous types for databound web controls

Published by on
Tags:

When using data bound controls it can sometimes be a pain to ship data across to web control you want to bind the data to. For example lets take a repeater control. Our application is quite simple, we have a person object containing name and date of birth, our application then takes this information and calculates which year they turned 18. The code for the Person class looks like this:

public class Person{
    public string Name{get;set;}
    public DateTime DoB{get;set;}
}

And the bit doing the calculation like so:

        List people = GetPeople();
people.ForEach(x =>
{
int year = GetYearTurned18(x);
});

At the moment very simple but I am not doing anything with the calculated value except assign it to a variable. What I want to do is pass all this to a repeater control so that I can then render it nicely on screen. The result should look like this:

Mike 23/03/1976 1994
Fred 21/07/1980 1998

So I want to bind it to a repeater a control by passing it to the DataSource property and then calling DataBind. I can't just pass both the person object and the calculated year into the DataSource because it only takes a single object, so I need to work out some other method.

The first thing might be to turn the calculation into a method on the person class like so, this will allow be to pass a list of Person objects to the DataSource. 

public class Person{
    public string Name{get;set;}
    public DateTime DoB{get;set;}
    private int YearTurned18
    {
        get
        {
            return this.DoB.Year + 18;
        }
    }
}

However what if we wanted to calculate the year they turned 16 or 24 or 65? We would have to write additional properties. It is not a good solution because of all the additional methods.

The second solution is to create a class to contain the person and year, something like:

    public class PersonContainer
    {
        public Person Person { get; set; }
        public int Year { get; set; }
    }	

This again is still not great, what if at some time in the future I want to pass the person object over with another value that isn't an int. I would have to either add another property to this class or create another class. Adding properties leaves me with a class where only a few peoperties are used or I have lots of container classes in my code.

A better solution is to use anonymous types. These types allow you to create classes with read only properties which you assign when the object is created. The code for our solution then becomes:

            List<Person> people = GetPeople();
            List<object> peopleData = new List<object>();
            
            people.ForEach(x =>
            {
                int year = GetYearTurned18(x);
                peopleData.Add(new { Person = x, Year = year });
            });

            _peopleRepeater.DataSource = peopleData;
            _peopleRepeater.DataBind();

This is quite nice. I can create this anonymous type and then in my repeater control get access to the data using the following: 

                        <%# DataBinder.Eval(Container.DataItem, "Person.Name") %>
                        <%# DataBinder.Eval(Container.DataItem, "Person.DoB", "dd/MM/yyyy") %>
                        <%# DataBinder.Eval(Container.DataItem, "Year")%>

I can also add as many other properties as I like to my anonymous type, allowing for easy expansion later on. However the only real problem is that the list is not strongly typed. I could add anything to the list because it accepts an object. So I want to make this more strongly typed.  However there is a way around this, read the post at the end of Microsoft's Anonymous Types page for a way to do this.

Sitecore Standard Template Tricks

Published by on
Tags:

The Sitecore standard template is the base template that pretty much every item you create in Sitecore inherits from. This means that the standard template is a very useful when you need to apply custom fields across every item in Sitecore. I recently had to do this for a project that involve a tagging system where the client wanted to tag everything including media items; I didn’t want to have to add the tagging template to the list of base templates for each item. However there are a few things you have to watch.

First to add you custom fields to the Standard Template start by creating a template to contain your custom fields. For this example I have called the template Demo Standard and then added it to the base template of the Standard Template, like so:

 

However if you now save this template and look at the Sitecore logs you will notice that Sitecore goes crazy telling you that you have circular template references:



This is caused because the new template you created inherits from the Standard Template. The solution is to change the base template from which you inherit from. To do this go to the database browser page at http://youdomain/sitecore/admin/dbbrowser.aspx and find your new item. Look at the base templates field and you will see it is empty. The empty space means it will inherit from the Standard Template:



If we look at the other templates added to the Standard Template we will see that the base template guid entered is an empty guid. So lets enter that into our new template:

We now see that this stops the errors appearing in the error log. So we can now go to one of our items a check the Standard Fields check box to see our custom fields: 



This is ok but the problem with this solution is that the user has to check the Standard Fields button to see my new custom fields and some users don't even have access to the standard fields checkbox. The way around this is to ensure that the base template guid is not an empty guid. However we have seen that if you enter the guid of another template or leave it blank you get a circular reference problem. You might try just entering a random guid and see what happens, however doing this will cause Sitecore to throw an error because it can’t find the base template you specified.
Instead we have to create a dummy template.The dummy template must have an empty guid for its base template like our original template. 


Once you have created this template and changed the base template guid to empty you can now make your original template inherit from this dummy template:



Now we can visit an item in Sitecore and see that our new custom fields are visible without the user having to check anything. This is because the Standard Fields check box only hides templates that have a base template with an empty guid and our new template does not. All your users should now be able to see this template no matter which item they look at in Sitecore.

 

Images and JavaScript

Published by on
Tags:

Thought I would blog this after I found this rather strange JavaScript behaviour. The scenario is that I have a list of items which display a short description. Clicking the button then expands the short description to the full description.  I decided on a simple solution, I would have a hidden element that contained the full description. When the user clicked the expand button the short description would hide and the full description would display. This was easy but I wanted an animation to play when this happened, this is when it got interesting. This was my first try. See what happens when you click the arrows:

  • My Title

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam pulvinar tortor non nisl. Nam eget libero ut nibh iaculis fringilla. In elit. Morbi ut nisi. Nam vitae magna. Suspendisse potenti. Proin venenatis, tortor iaculis consequat pellentesque, nulla lorem sollicitudin sem, in pulvinar nisl sem sit amet nisl. Donec eros metus, viverra in, pretium aliquam, porttitor vitae, magna. Maecenas vel sapien quis lectus pretium ultrices.

  • My Title

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam pulvinar tortor non nisl. Nam eget libero ut nibh iaculis fringilla. In elit. Morbi ut nisi. Nam vitae magna. Suspendisse potenti. Proin venenatis, tortor iaculis consequat pellentesque, nulla lorem sollicitudin sem, in pulvinar nisl sem sit amet nisl. Donec eros metus, viverra in, pretium aliquam, porttitor vitae, magna. Maecenas vel sapien quis lectus pretium ultrices.

If you click both images several times you will start to see that both arrows move, not what I wanted. This was something I didn’t expect, however after a little thinking this suddenly made sense. The code I was using to swap the images was:

   30         function ImageSwap(elementId, imageUrl1, imageUrl2){

   31             var obj = document.getElementById(elementId);      

   32 

   33             if(obj.getAttributeNode("src").value.indexOf(imageUrl1) >-1){   

   34                 obj.getAttributeNode("src").value = imageUrl2;

   35             }

   36             else{

   37                 obj.getAttributeNode("src").value = imageUrl1;

   38             }

   39         }           

This tells the browser to change the source of the image on the target element. However at certain times both arrow images point to the same image " /image.axd?picture=2008%2f9%2fArrowLeftToRight.gif"; so when I tell the browser to change the image the browser plays the animation again, any other element that points at this image automatically plays the image again because they all look at the same in memory object. So what was the solution? Well I needed a way to ensure that each image was held uniquely in memory. One sure way to do this is to change the URL. If the URL to image is different the browser has to load it into a separate object in memory because it might slightly differently. The easiest way to do this is to append a query string value that means nothing to the end of the URL. The server will ignore the additional value but the browser will think that it is a different image. Hence the following JavaScript

 

   40         function ImageSwap2(elementId, imageUrl1, imageUrl2){

   41             var obj = document.getElementById(elementId);      

   42 

   43             if(obj.getAttributeNode("src").value.indexOf(imageUrl1) >-1){   

   44                 obj.getAttributeNode("src").value = imageUrl2+"&"+elementId;

   45             }

   46             else{

   47                 obj.getAttributeNode("src").value = imageUrl1+"&"+elementId;

   48             }

   49         }

 

 You can see the result below:

 

  • My Title

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam pulvinar tortor non nisl. Nam eget libero ut nibh iaculis fringilla. In elit. Morbi ut nisi. Nam vitae magna. Suspendisse potenti. Proin venenatis, tortor iaculis consequat pellentesque, nulla lorem sollicitudin sem, in pulvinar nisl sem sit amet nisl. Donec eros metus, viverra in, pretium aliquam, porttitor vitae, magna. Maecenas vel sapien quis lectus pretium ultrices.

  • My Title

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum blandit molestie nunc. Ut aliquet egestas lorem. In hac habitasse platea dictumst. Nulla orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam pulvinar tortor non nisl. Nam eget libero ut nibh iaculis fringilla. In elit. Morbi ut nisi. Nam vitae magna. Suspendisse potenti. Proin venenatis, tortor iaculis consequat pellentesque, nulla lorem sollicitudin sem, in pulvinar nisl sem sit amet nisl. Donec eros metus, viverra in, pretium aliquam, porttitor vitae, magna. Maecenas vel sapien quis lectus pretium ultrices.

However one thing to consider is that like all solutions there are down sides, the main one being that each image has to be retrieved individually even though it really is the same image. This means a lot more HTTP traffic to your site and possibly slower page load times. If you have short lists then this is not to much of a problem but on longer list it could be a lot more data. For example if I use the images above they are about 1Kb in size each; for each list item I have to load at least one arrow, so if I have a list of 50 items that 50Kb plus then and additional 1Kb each time and image is clicked. 

Useful Links

Published by on
Tags:

Ok its been a week since I added anything, I have not been lazy, I have been off on holiday. I spent a few days at home and then a couple of days on the beach, it was nice and a good break from coding.

Anyway I came back and decided to publish a list of useful links. These links contain bits of information that I think are useful or interesting (I hope you do to). If you have any suggestions for more links to add please let me know. You can find the useful links page at http://www.fousty.net/page/Interesting-Links.aspx.

Push Up The Web

Published by on
Tags:

It is a busy blog day but I have just add a little tool from http://www.pushuptheweb.com. This brilliant piece of JavaScript and images displays a small reminder to users if their browser is out of date and needs updating. It works for a variety of browsers; Firefox, IE, Safari and Opera. The web has needed something like this for a while; developing web sites is a bizarre job. I can not think of many industries where they have to ensure that their product will work perfectly on technology that is years out of date and been replaced by several newer versions especially when those new versions are free, but this is the problem we web developers face. Maybe this small tool will start to bring users up to date.
 

 

All blogs tagged with 'web'

Projects

Have you read?

Sitecore Sheer XAML Applications - Part 1



Blogs by date