Skip to content

Nano ViewModel Support

Nano view model is very small library to build MVVM enabled Silverlight/WPF/WP7 based application.MVVM becomes more and more popular in fast few years and there are many implementations  like MVVM Light toolkit, Prism(Last Version), nRoute, or Caliburn however these libraries have too many features and keep on growing which could have adverse effect on you project in terms of performance etc.For example communication between view in MVVM Light Toolkit is based on silverlight messaging which may not be best if you working ithin single silverlight application.It can be used when you page have more than one silverlight application (xap files) which requires communication and what about if you are not intead to use some of the feature from the toolkits i.e you want just the MVVM but you end up with adding complete set of library in your project.What if you need some features from MVVM Toolkit and you too want to use prism library.

There are a number of benefits this pattern brings to both WPF and Silverlight development. Before you go on, ask yourself:

  • Do you need to share a project with a designer, and have the flexibility for design work and development work to happen near-simultaneously?
  • Do you require thorough unit testing for your solutions?
  • Is it important for you to have reusable components, both within and across projects in your organization?
  • Would you like more flexibility to change your user interface without having to refactor other logic in the code base?

MVVM is not just about resuability,blendability & testability however its very power and if used properly you could create low latency WPF based applications.If you want to know about the theory you may follow the post here or google it and you will find many discussions and articles on MVVM.

Below are the features supported by NanoVmSupport library

  • Minimum code in you view model.
  • No nead to have obvervable properties and extra code with each property.
  • Supports command implementation.
  • Command binding for all most all controls using EventToCommand implementation
  • Provision to set design time data for view model (supports blendability)
  • NanoVmSupport.Events libaray supports communication between two view models in you application.It is extracted from Prism library so you if you are familiar with prism its very easy for your.Please note that you don’t have to use prism to use this.If few months later support you want prism, you may exclude NanoVmSupport.Events library and your code will start using eventing from prism with just chnaging single line of initilization.
  • You can easyly write unit tests against your view models.

The sample silverlight application below (MVVM & library MVVM.Events) is the implement of NanoVMSupport & NanoVMsupport.Events.The source code for sample project and NanoVMSupport library can be downloaded from here and if required binaries are here.

Install Microsoft Silverlight

The sample folder in the source code also includes sample application code for silverlight and WPF.The WPF application is Auction Sniper for madbid which places your bids automaticaly based on some figures/process.
For communication between viewmodels check the documentation from prism or send me your queries in this post,for Microsoft Unity Application block click here.

MVVM common Issues & fixes in NanoVMSupport :

  • Standard Silverlight TextBox control is very useful but has one strange behavior: if you use TwoWay data binding and bind some property to controls Text property, when users type text into the control, this change is not propagated to the bound property until the control loses its focus. The AutoComit Behavior for textbox control is now part of NanoVMSupport Library (Lib for MVVM) for detail check this article “Silverlight TextBox AutoComit Behaviour“.
  • How to invalidate the CanExecute value : Suppose you have textbox and command button ,Can execute returns false if the length of text is zero otherwise it returns true and you have also used the above mentioned Auto Comit behaviour on text box.CanExecute will be re-evaluated when something interesting within the application’s window happens in WPF however in silverlight or with NanoVMSupport library you have to explictly update the ICommand.The one way of doing this is to change “RaisePropertyChange” method in ViewModelBase.cs as mentioned below
    protected void RaisePropertyChanged(string name)
    {
        PropertyChanged.Raise(this, name);
        PropertyChanged.Raise(this, "");

    }

    The code line PropertyChanged.Raise(this, “”); will refresh all the properties and icommands on view.But it may have performance issues if you have may properties and commands in viewmodal.The another recommended approach is to use following code in viewmodal

    public string SelectedText
    {
        get { return Get(() => SelectedText); }
        set
        {
            Set(() => SelectedText, value);
            base.RaisePropertyChanged("SearchCommand");
        }
    }

    The code base.RaisePropertyChanged(“SearchCommand”); will invalidate the SearchCommand.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

.Net Script Editor (C#,Vb.net Mini IDE)

Complete Visual Studio IDE (source code included) in single user contol that can be used in your windows application to provide scripting feature in languages like c# abd vb.net.IDE have features like code intellisence,reference to .Net assemblies,COM libraries & web services.The code editor supports lot coloring for languages like c,c++ c#,vb.net,sql etc..Refrectoring features like converting c# code to vb.net code in single click.

 Add scripting functionality to your application,features of MS Script control (Functions like AddObject) and some features of VSA/Visual Studio editor like intellisence, code completion etc. Mini .Net IDE in single winform control.

The source code / article published here is to provide features of MS Script control (Functions like AddObject) and some features of VSA/Visual Studio editor like intellisence, code completion etc. The control supports C# and VB.net language however can be easily modified to support any .net language. You can use COM references, .Net references & Web References. The control supports Visual studio IDE features like bookmark, highlighting interpreter errors & compiler errors, adding multiple classes and interfaces. You can imagine visual studio IDE build in single control with feature like AddObject from MS Script Control. To use this control you just need to drag and drop it to your winforms and add few lines of code to add instance of object which you want to access in the scripts.

Source code at :
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Silverlight Page Flip

Page flip is a very impressive features in displaying your documents, images, media, etc.. The technique behind page flip is pretty complicated. Below is the page flip live application & source code link.

Install Microsoft Silverlight

You can download the source code here (VS 2010).

I could not spare much time to write implementation notes , however, Rick Barraza has a very good articles describing all the mystery behind this technique in his post. The code is based on his article and can be further extended to create silverlight generic control which could even flip silverlight pages, documents, images etc.

Another interested implementation of page turn effect is available on Microsoft by Jeff & Mitsu’s.

Another page flip (book) control is available here

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Silverlight Database

The Silverlight library in this article extends RIA service entities and provides save & load method to save/load entities directly into application storage (Isolation storage). The library supports dynamic quota management for application storage i.e. if an entity requires more space to store it will prompt user to confirm new size of quota store. The saving and loading supports asynchronous processing of entities with inbuilt compression which allows your application to provide non blocking UI. Library can be used to build online-offline mode based Silverlight applications without additional programming overheads.

Code to save RIA Entities in the storage space

PatientContext context = new PatientContext();
dataGrid.ItemSource = context.Patients;
Action<LoadOperation<Patient>> completeProcessing = delegate(LoadOperation<Patient> loadOp)
{
    if (!loadOp.HasError)
        {
            loadOp.Entities.Save();
        }
        else
        {
            LogAndNotify(loadOp.Error);
            loadOp.MarkErrorAsHandled();
        }
};
context.Load(context.GetPatientsQuery(), completeProcessing, null);

Code to load RIA Entities from storage space

PatientContext context = new PatientContext();
context.Patients.Load();

You can also use the same library to save and load genric data you need to provide the filename to which the object set is saved whereas with Ria EntitySet the fileName is optional which is calculated based on the data type of entity.
Code to save List<string> into storge sapce

List<string> names = new List<string>();
names.Add("Employee1");
names.Add("Employee2");
names.Add("Employee3");
names.Save("Employee4");
names.Save("EmployeeesDataSet");

Code to load List<string> into storge sapce

List<string> names = new List<string>();
names.Load("EmployeeesDataSet")

Note: The Load method supports Asynchronous (default) and Synchronous operation where as Save method only supports Asynchronous operation.You can also override the Quota Management screen globally in your application and if not overrided the library will use in-built screen shown below (right image).

How it works : diagram is self explanatory..

Source code is now available here, Because of time constriants i was not able to comlete the code behind for the isolation storage screen above, however the library is now completed and published with silverlight unit test project.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Page flip with deep zoom

Book control is another excellent page flip control which allows you to add any silverlight element as book page.It supports page down and page up as bidiretional navigation keys.Demo application & source code is attached below.

Install Microsoft Silverlight

The objective of this article is to create photo album application which allows user to add pictures just by drag and drop on album.The picture will be splitted into parts and uploaded on server where it is re-constructed and again processed into deep zoom meta file (on fly) and link to this picture will be then added into album.Photo album will have deep zoom enabled pages.

I couldn’t get much time to finish this project & hence i would call this as beta source code which includes the full source code of Book control (page flip)

Beta Source code for book control is available here

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

@@servername

If @@servername returns null or return wrong host name, execute below mentioned sql Query.


DECLARE @Current SysName
Select @Current = Convert(varchar(128), SERVERPROPERTY(‘ServerName’) )
IF(@Current <> @@SERVERNAME)
BEGIN
EXEC sp_dropserver @@SERVERNAME
EXEC sp_addserver @server=@Current,@local = ‘local’
EXEC master..xp_cmdshell ‘ECHO NET STOP MSSQLSERVER > restartSQL.bat’, no_output
EXEC master..xp_cmdshell ‘ECHO NET START MSSQLSERVER >> restartSQL.bat’, no_output
EXEC master..xp_cmdshell ‘restartSQL.bat’, no_output
–Connection with sql break here
END

– Check if every thing is correct
SELECT @@Servername
SELECT SERVERPROPERTY(‘ServerName’)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Export data from corrupted database

Below is the sql script to import data from source database into target database, It is assumed that you have both the databases on single server.The source database is current database & few tables are corrupted whereas the traget database is created from old backup for target database.since their is corruption ,it is not possible to take backup of current database. This script imports back data (only) from source to target database. You need to only replace 3 lines of the script (12th line from bottom).
Download script from here

 

————- Create helper functions —————————–

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N‘[dbo].[Mig_ImportTable]‘) AND OBJECTPROPERTY(id, N‘IsProcedure’) = 1)
DROP PROCEDURE [dbo].[Mig_ImportTable]
GO

CREATE PROC dbo.Mig_ImportTable @DATABASE SYSNAME, @TABLE SYSNAME AS
        SET NOCOUNT ON

        DECLARE @COLUMN SYSNAME
        DECLARE @SQL NVARCHAR(4000)
        DECLARE @colSQL NVARCHAR(4000)
        DECLARE @IsIdentity BIT
        DECLARE @IsTableIdentity BIT

        SET @colSQL =
        SET @SQL=
        SET @IsTableIdentity = 0 –false
        SET @IsIdentity = 0 –false

        PRINT ‘Table Migration Started for :’ + @TABLE + ‘ in ‘ + @DATABASE

        DECLARE curMoveDown CURSOR
        LOCAL FORWARD_ONLY
        OPTIMISTIC FOR
        SELECT column_name,COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, ‘IsIdentity’)AS IsIdentity FROM information_schema.COLUMNS
        WHERE UPPER(table_name ) = UPPER(@TABLE)

        OPEN curMoveDown FETCH NEXT FROM curMoveDown INTO @COLUMN,@IsIdentity
        WHILE @@FETCH_STATUS = 0
        BEGIN
                SET @colSQL = @colSQL + ‘[' + @COLUMN + '],’
                SET @IsTableIdentity = @IsTableIdentity | @IsIdentity
                IF (@IsTableIdentity = 1) BREAK
                FETCH NEXT FROM curMoveDown INTO @COLUMN,@IsIdentity
        END
        CLOSE curMoveDown
        DEALLOCATE curMoveDown

        IF(LEN(@colSQL)>1)
        BEGIN
                SET @colSQL = LEFT(@colSQL,LEN(@colSQL)1)

                IF(@IsTableIdentity = 1) SET @SQL = @SQL + ‘SET IDENTITY_INSERT ‘ + @TABLE + ‘ ON ‘
                SET @SQL = @SQL + ‘     ALTER TABLE ‘ + @TABLE + ‘ DISABLE TRIGGER ALL ‘
                SET @SQL = @SQL + ‘     ALTER TABLE ‘ + @TABLE + ‘ NOCHECK CONSTRAINT ALL ‘
                SET @SQL = @SQL + ‘     TRUNCATE TABLE ‘ + @TABLE + ‘  ’
                IF(@IsTableIdentity = 1)
                        SET @SQL = @SQL + ‘     INSERT INTO ‘ + @TABLE + ‘ (‘ +  @colSQL + ‘) SELECT ‘+  @colSQL + ‘ FROM ‘ + ‘[' + @DATABASE + '].[dbo].[' + @TABLE + '] ‘
                ELSE
                        SET @SQL = @SQL + ‘     INSERT INTO ‘ + @TABLE + ‘ SELECT * FROM ‘ + ‘[' + @DATABASE + '].[dbo].[' + @TABLE + '] ‘
                IF(@IsTableIdentity = 1) SET @SQL = @SQL + ‘    SET IDENTITY_INSERT ‘ + @TABLE + ‘ OFF ‘
                SET @SQL = @SQL + ‘     ALTER TABLE ‘ + @TABLE + ‘ ENABLE TRIGGER ALL ‘
                SET @SQL = @SQL + ‘     ALTER TABLE ‘ + @TABLE + ‘ CHECK CONSTRAINT ALL ‘

                EXEC sp_executesql @SQL
                PRINT ‘Table migrated :’ + @TABLE
        END
        ELSE
                PRINT ‘No Column found :’ + @TABLE + ‘ (SQL = ‘ + @colSQL + ‘)’

        PRINT ‘Table Migration finished for :’ + @TABLE
GO

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N‘[dbo].[Mig_ImportDatabase]‘) AND OBJECTPROPERTY(id, N‘IsProcedure’) = 1)
DROP PROCEDURE [dbo].[Mig_ImportDatabase]
GO

CREATE PROC dbo.Mig_ImportDatabase @Source SYSNAME AS   

        DECLARE @SERVER SYSNAME
        DECLARE @INSTANCE SYSNAME
        DECLARE @FULLNAME SYSNAME
        DECLARE @DBNAME SYSNAME
        DECLARE @cmd varchar(1000)
        DECLARE @SQL Nvarchar(1000)
        DECLARE @TABLE Nvarchar(100)
        DECLARE @Result INT

        SET NOCOUNT ON

        CREATE TABLE [#Mig_FailedTables] ( [name] SYSNAME NOT NULL ) ON [PRIMARY]

        SELECT @SERVER = CONVERT(SYSNAME, SERVERPROPERTY(‘servername’))
        SELECT @INSTANCE = IsNull(,CONVERT(SYSNAME, SERVERPROPERTY(‘InstanceName’)))
        SELECT @DBNAME = DB_NAME()

        IF(Len(@INSTANCE)>0) SET @FULLNAME = @SERVER + \’ + @INSTANCE
        ELSE SET @FULLNAME = @SERVER

        Print ‘Migration started FROM DATABASE [‘ + @SOURCE + ‘] TO DATABASE [‘ + @DBNAME + ‘] ON server  ‘ + @FULLNAME

        –Cursor to loop throw all tables of Target database (current database)
        DECLARE CurTables CURSOR LOCAL FORWARD_ONLY
        OPTIMISTIC FOR
        SELECT NAME from dbo.sysobjects where OBJECTPROPERTY(id, N’IsUserTable‘) = 1 order by Name

        OPEN CurTables FETCH NEXT FROM CurTables INTO @Table
        WHILE @@FETCH_STATUS = 0
        BEGIN
                Print ‘Migrating TABLE ‘ + @Table
                SET @cmd = ‘
ECHO Exec [Mig_ImportTable] ‘ + @Source + ‘,‘ + @Table + ‘  > DbMig.sql
                EXEC @Result = master..xp_cmdshell @cmd, no_output

                SET @cmd = ‘ECHO GO  >> DbMig.sql
                EXEC @Result =  master..xp_cmdshell @cmd, no_output

                SET @cmd = ‘ECHO @ECHO OFF  > DbMig.cmd
                EXEC @Result =  master..xp_cmdshell @cmd, no_output

                SET @cmd = ‘ECHO osql -E -b -S "’ + @FULLNAME +’" -d "’ + @DBNAME +’" -i "DbMig.sql" >> DbMig.cmd
                EXEC @Result =  master..xp_cmdshell @cmd, no_output

                SET @cmd = ‘ECHO EXIT ERRORLEVEL >> DbMig.cmd
                EXEC @Result =  master..xp_cmdshell @cmd, no_output

                SET @cmd = ‘CMD /c "DbMig.cmd>>DbMig.Log"
                EXEC @Result = master..xp_cmdshell @cmd, no_output
                IF (@Result <> 0)
                        Insert into #Mig_FailedTables (Name) values (@Table)
                FETCH NEXT FROM CurTables INTO @Table

        END
        CLOSE CurTables
        DEALLOCATE CurTables
        Print ‘Migration Finished..
        SELECT Name as [Failed Tables] FROM #Mig_FailedTables
        DROP TABLE #Mig_FailedTables

GO

————- Migration of data starts from here ——————

———————————————————————————————————————————-

USE TargetDatabase                                              — Target Database      ** Change This
Exec Mig_ImportDatabase ‘SourceDatabase‘                        — Source Database      ** Change This – Import Complete database
EXEC Mig_ImportTable ‘
SourceDatabase‘,’SpecificTableName‘       – SpecificTableName    ** Change This – Import Single Table
———————————————————————————————————————————-

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Compare DB – record counts

Code snippet will loop through all tables of Database SOURCEDB and compare record counts with tables in TARGETDB database

USE SOURCEDB

EXEC SP_MSforeachtable ‘DECLARE @OriCount INT
     DECLARE @Count INT
     DECLARE @Name VARCHAR(400)
     SET @Count = (SELECT COUNT(*) FROM TARGETDB.?)
     SET @OriCount = (SELECT COUNT(*) FROM SOURCEDB.?)
     SET @Name=”?”

IF(@Count <> @OriCount)
BEGIN
         SELECT @Name,@Count as target,@OriCount as source

END

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Xap Loader Splash Screen

 

Install Microsoft Silverlight

The objective of this article is to create custom xap loader screen without any background image and code behind (pure XAML).In the final application version, download progress of root xap file will be shown in the sample screen above..

Will write more on this article in next few days …

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Silverlight for Symbian S60 devices

Microsoft has released Silverlight platform design to work with Symbian S60 devices at the on MIX10 conference at Las Vegas.The plateform is now available for Nokia SymbianOS (S60 5th Edition) devices i.e. Nokia 5235, 5800 XpressMusic, Nokia N97 and Nokia N97 Mini Mobiles. I did some basic test with nokia 5235 and it runs with charm.

The current Silverlight beta for Symbian comes in two forms – one as an installer for Symbian (S60 5th edition) devices and the second one in the form of a developer tools suite for developing Silverlight applications for Symbian devices including emulator etc.

Silverlight includes a Runtime that is optimized to display content on memory-constrained devices.

  •  The ability to view Silverlight applications in the mobile browser.
  •  Tools to build Silverlight applications that target devices

Microsoft has bought the Silverlight platform to a non-Microsoft mobile platform for the first time ever.

In order to get started with Silverlight for Symbian, you will want to familiarize yourself with the platform capabilities.

More resources are available on microsoft website.

Days are not far when you will see silverlight on rest of consumer devices ..

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Silverlight TextBox AutoComit Behaviour

Standard Silverlight TextBox control is very useful but has one strange behavior: if you use TwoWay data binding and bind some property to controls Text property, when users type text into the control, this change is not propagated to the bound property until the control loses its focus.  

This can be very annoying if you have MVVM application and you have some kind of real-time filter that needs to update some data as-you-type.  

In TwoWay bindings, changes to the target automatically update the source, except when binding to the Text property of a TextBox. In this case, the update occurs when the TextBox loses focus (in case of element to element binding the text box behaviour is normal) .  

You can disable automatic source updates and update the source at times of your choosing. For example, you can do this to validate user input from multiple controls before you update the bound data sources.  

You must update the source for each binding individually, however. To update a binding, first call the FrameworkElement.GetBindingExpression method of a target element, passing in the target DependencyProperty. You can then use the return value to call the BindingExpression.UpdateSource method. The following example code demonstrates this process  

 Problem is that TextBox control does not call BindingExpression.UpdateSource when its Text property is changed so we have to do that manually in order to fix this issue.The AutoComit Behavior for textbox control is now part of NanoVMSupport Library (Lib for MVVM)  

public class AutoCommit : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
    }

    private void AssociatedObjectOnTextChanged(object sender, TextChangedEventArgs args)
    {
        var bindingExpr = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
        if(bindingExpr != null) bindingExpr.UpdateSource();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
        base.OnDetaching();
    }
}

And the xaml is  

<TextBox Text=”{Binding SearchText,Mode=TwoWay}”> 
 <i:Interaction.Behaviors> 
<NanoVM:AutoCommit/> 
</i:Interaction.Behaviors> 
</TextBox> 

Another approach to solve this issue is to create TextBoxEx class drived from TextBox.With this approach the xaml size will be highly reduced as for each text box in your application it would save around 90 chars in xaml.

public class TextBoxEx : TextBox
{
    public TextBoxEx()
    {
        this.Loaded += new RoutedEventHandler(TextBoxEx_Loaded);
    }

    void TextBoxEx_Loaded(object sender, RoutedEventArgs e)
    {
        this.TextChanged += new TextChangedEventHandler(TextBoxEx_TextChanged);
    }

    void TextBoxEx_TextChanged(object sender, TextChangedEventArgs e)
    {
        var source = sender as TextBox;
        if (source != null)
        {
            var bindingExpression = source.GetBindingExpression(TextBox.TextProperty);
            if (bindingExpression != null)
            {
                bindingExpression.UpdateSource();
            }
        }
    }

}

and xaml in this case is 

<ctrls:TextBoxEx Text=”{Binding SearchText,Mode=TwoWay}”/>

However the above behaviour give you more control of how text box behaves.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)