Monday, March 30, 2009

Silverlight 3 Beta Local Messaging among Silverlight islands

If you have read my previous post about inter silverlight communication design you might seen how difficult it is to accomplish communication between 2 silverlight applications hosted in same page.But in Silverlight 3 Microsoft has introduced a new technique to do the communication.It is nothing but 2 classes.LocalMessageSender & LocalMessageReceiver.Now it is very easy to accomplish communication between islands of Silverlight contents.

Implementing Local messaging between silverlight applications
As like in other communication scenarios here also there should be a source and destination which sends and receives respectively.LocalMessageSender class sends a string message and LocalMessageReceiver receives the same.At the time of sending we should specify the name of the receiver.Also at the time of listening for message we should give the name of receiver.ie it denotes which messages it should capture based on the receiver name.
LocalMessageSender : The constructor of this class accepts the receiver name.To send the message we have to use the method SendAsync.The SendCompleted event is fired after completion of sending process.
LocalMessageReceiver : The constructor of this class also got a parameter to specify the receiver name.MessageReceived is the event which will fire when a message comes with the corresponding receiver name.After subscribing into this event the Listen Method need to be called in order to start listening.

Creating Visual Studio Solution structure
Here I have used 3 projects 2 Silverlight projects one is source and next is destination,and one asp.net application which hosts these 2 Silverlight applications.

Default.aspx

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div  style="height:100%;">
<asp:Silverlight ID="Silverlight1" runat="server" 
Source="~/ClientBin/LocalMessagingSource.xap" MinimumVersion="3.0.40307.0" 
Width="400" Height="100"/>
</div>
<div>
Your html contents goes here..
<h1>Heading</h1>
<h3>Sub heading</h3>
<p>contents</p>
</div>
<div  style="height:100%;">
<asp:Silverlight ID="Silverlight2" runat="server" 
Source="~/ClientBin/LocalMessagingDestination.xap" MinimumVersion="3.0.40307.0" 
Width="400" Height="100" />
</div>
</form>


 MainPage.xaml in project LocalMessageSource


<UserControl x:Class="LocalMessagingSource.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot"
Background="AliceBlue"
Height="100"
Width="400">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2"
HorizontalAlignment="Center">I am sender</TextBlock>
<TextBlock Grid.Row="1">Message</TextBlock>
<TextBox Grid.Row="1"
x:Name="txtMsg"
Grid.Column="1"
Text="" />
<Button Grid.Row="2"
Content="Send"
Click="Button_Click" />
<TextBlock x:Name="txtStatus"
Grid.Row="2"
Grid.Column="1" />
</Grid>
</UserControl>


MainPage.xaml.cs in project LocalMessageSource


private void Button_Click(object sender, RoutedEventArgs e)
{
LocalMessageSender msgSender = new LocalMessageSender("receiver");
msgSender.SendCompleted += new EventHandler<SendCompletedEventArgs>(msgSender_SendCompleted);
msgSender.SendAsync(txtMsg.Text); 
}

void msgSender_SendCompleted(object sender, SendCompletedEventArgs e)
{
txtStatus.Text = "Send";
}


MainPage.xaml.cs in project LocalMessageDestination


<UserControl x:Class="LocalMessagingDestination.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400"
Height="100">
<Grid x:Name="LayoutRoot"
Background="LightGoldenrodYellow">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2"
HorizontalAlignment="Center">I am receiver</TextBlock>
<TextBlock Text="Received messag"
Grid.Row="1" />
<TextBox x:Name="txtMessage"
Grid.Row="1"
Grid.Column="1" />
</Grid>
</UserControl>


MainPage.xaml.cs in project LocalMessageDestination

public MainPage()
{
InitializeComponent();
LocalMessageReceiver receiver = new LocalMessageReceiver("receiver");

receiver.MessageReceived += new EventHandler<MessageReceivedEventArgs>(receiver_MessageReceived);
receiver.Listen();
}

void receiver_MessageReceived(object sender, MessageReceivedEventArgs e)
{
txtMessage.Text = e.Message;
}



Sample can be downloaded from here.

There are so many options with this messaging APIs such as domain blocking etc.You can send to some specific domains by using these options.More details later…

NB:This post is written using Silverlight 3 Beta.Things may change in Actual release.

Saturday, March 28, 2009

Silverlight 3 Beta Deep linking using Navigation application

The main disadvantage of earlier RIA technologies like Flash and Silverlight 2 was the absence of Deep linking.ie we can’t maintain a link to a specific screen or page in the RIA application.We can see just same URL even we change screens or pages in RIA application.Hence we can’t give a specific url to somebody or book mark that screen by url.Each time when the RIA application loads we have to navigate again to reach a specific page.That is very much time consuming.
Eg: If we want to have a profile page in our application how will we handle that in ASP.Net ? it’s simply addressed by using a page called profile.aspx with querystring ?id=10
This was not possible in Silverlight until the release of Silverlight 3 and it’s Navigation application support.With the introduction of navigation support we can maintain constant links to specific screens in the Silverlight RIA application.Hence we can distribute that link and bookmark that Silverlight page.

Creating a deep linked address book application using Silverlight
Since the main aim is to demonstrate deep linking ,I am using a simple Person class with properties Id ,Name and Address.The data storage is an Xml file.Here is the Person class.

public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }


Designing Data access
The PersonDataContext class provides the required Data.AllPersons and GetPersonById are the members which returns collection of all persons and Person by id respectively.


public class PersonDataContext
{
    XDocument _doc;
    private XDocument XmlDoc
    {
        get
        {
            if (_doc == null)
            {
                 _doc = XDocument.Load("Persons.xml");
            }
            return _doc;
        }
    }
    public IEnumerable<Person> AllPersons
    {
        get
        {
            return from li in XmlDoc.Root.Elements()
                   select new Person()
                   {
                       ID = Convert.ToInt32(li.Attribute("Id").Value),
                       Name = li.Attribute("Name").Value,
                       Address = li.Attribute("Address").Value
                   };
        }
    }
    public Person GetPersonById(int id)
    {
        XElement ele= XmlDoc.Root.Elements().First(s => s.Attribute("Id").Value == id.ToString());
        Person person=null;
        if(ele !=null)
        {
            person = new Person()
            {
                ID = Convert.ToInt32(ele.Attribute("Id").Value),
                Name = ele.Attribute("Name").Value,
                Address = ele.Attribute("Address").Value
            };
        }
        return person;
    }
}


Building User Interface

We are using a ListBox to display the list of persons in the HomePage.xaml.The ItemTemplate of the ListBox contains a hyperlink button and its NavigateUri is binded to Person object using a converter named Person2UriConverter.We are using a converter because the NavigateUri expects a object of type Uri.One more thing is that we don’t have path to details page in Person class.So we used a converter which combines the page url with the newly created name value pair.

HomePage.xaml


<navigation:Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
                 xmlns:local="clr-namespace:AddressBook"
                 x:Class="SilverlightApplication1.HomePage"
                 xmlns:conv="clr-namespace:AddressBoook.Converters"
                 Title="HomePage Page">
    <navigation:Page.Resources>
        <conv:Person2UriConverter x:Key="p2uri" />
        <local:PersonDataContext x:Key="PersonDataContextDataSource" />
        <DataTemplate x:Key="personDT">
            <StackPanel>
                <HyperlinkButton Content="{Binding Name}" NavigateUri="{Binding Converter={StaticResource p2uri}}"></HyperlinkButton>
            </StackPanel>
        </DataTemplate>
    </navigation:Page.Resources>
    <Grid x:Name="LayoutRoot" Background="White" >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListBox DataContext="{Binding Source={StaticResource PersonDataContextDataSource}}"
                 ItemsSource="{Binding Mode=OneWay, Path=AllPersons}"
                 ItemTemplate="{StaticResource personDT}" Grid.Row="1" />
        <TextBlock Text="Home" Style="{StaticResource HeaderTextStyle}"/>
    </Grid>
</navigation:Page>



Person2UriConverter.cs


public class Person2UriConverter:IValueConverter
    {
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Person person = value as Person;
            string localpath = System.Windows.Browser.HtmlPage.Document.DocumentUri.LocalPath;
            return new Uri(localpath+"#/Views/Person.xaml?id="+person.ID,UriKind.RelativeOrAbsolute);
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        #endregion
    }


Now we made the display of listbox with all persons.Now when run and click on the person link we can see the new url as http://localhost:61838/SilverlightApplication1TestPage.aspx#/Views/Person.xaml?id=1.It won’t display anything since there is no Person.xaml.Create the Person.xaml page which is going to be the detail view.

Creating detail page Person.xaml

Here the idea is to get the query string parameter id and load the Person class.This Person class is set as DataContext of the newly created a Page called Person.xaml where it is going to display the details.DataContext is setting on the overriden method OnNavigateTo.

Person.xaml.cs


// Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            int personId = Convert.ToInt32(this.NavigationContext.QueryString["id"]);
            this.DataContext = new PersonDataContext().GetPersonById(personId);
        }


Person.xaml

<navigation:Page x:Class="SilverlightApplication1.Views.Person" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           Title="Person Page">
    <Grid x:Name="LayoutRoot"
          Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Text="ID" />
        <TextBox Grid.Column="1"
                 Text="{Binding ID}" />
        <TextBlock Grid.Row="1"
                   Text="Name" />
        <TextBox Grid.Row="1"
                 Grid.Column="1"
                 Text="{Binding Name}" />
        <TextBlock Grid.Row="2"
                   Text="Address" />
        <TextBox Grid.Row="2"
                 Grid.Column="2"
                 Text="{Binding Address}" />
    </Grid>
</navigation:Page>



Now when we click on the Person link we will get the detail page Person.XAML.Now you can distribute the URL to your friends and you can yourself use that as bookmark in your browser.

Sample can be downloaded from here.

Friday, March 27, 2009

Silverlight 3 Beta Navigation Application support

This is another new feature added in Silverlight 3 which is based on WPF paging concept.Navigation or Paging support gives us flexibility to design our application as page wise.It is more likely to ASP.Net page concept than windows programming.There will be a container which contains pages and we can switch among pages by user actions as well as by programmatically.The main advantage of this is we can identify each Silverlight page by it’s url.We will discuss about this deep linking feature in a new post.

Creating Silverlight navigation application / paging enabled Application.

The Silverlight 3 tools for visual studio 2008 brings a new project template for Navigation application.Select that project template and create.The project template itself contains 3 sample Pages AboutPage.xaml,ErrorWindow.xaml and HomePage.xaml in the Views folder.


These pages are hosted in MainPage.xaml using a control called Frame coming from the assembly System.Windows.Controls.Navigation.The Source property of Frame denotes the current page which is displaying in Frame.Change the Source property if you need to change the current page.
When we run the application we can see a good style for the controls in it.That is not magic of paging but the effect of styles and templates present in App.xaml :-)

Switching among pages

There are 2 methods to switch current page.

this.Frame.Navigate(new Uri(“goToPageURI”, UriKind.Relative));
(Or)
this.Frame.Source = new Uri(“goToPageURI”, UriKind.Relative);

Controlling navigation / paging behavior

There are so many properties and methods available in Page and Frame classes to control the navigation behavior such as Frame.CanGoBack,Frame.CanGoForward,Frame.StopLoading() etc….Main requirement will be getting the query string parameters in the page in order to load something or show something.It is available in NavigationContext.QueryString property.

Note that the query string contains the name value pairs which comes after the ‘;’ symbol.You can’t get the path (Eg:#/Views/HomePage.xaml)to page there.

NB :The above post is written based on Silverlight 3 Beta build.Things may change in the actual release.

Wednesday, March 25, 2009

Silverlight 3 Beta Merged Resource Dictionaries

This helps us to link resource dictionaries.That means we can split up our resource dictionaries into small files and link them together to act like a single resource dictionary.

Earlier when we develop a Silverlight custom control library we have to keep all the control styles and templates in a single resource dictionary file called generic.xaml.That is very much confusing and makes the generic.xaml very huge and complex.We can’t maintain that resource dictionary easily.The main advantage of Merged resource dictionary comes here.We can split up the styles and templates of each individual Silverlight control into separate resource dictionary files and maintain easily.

Also when we are in styling or templating controls in a complex user control we can split up similar styles into different resource dictionaries.Normally its very useful to separate Brushes and colors from the styles.

Creating Resource Dictionary

If you are using Visual studio there is no direct support to add a ResourceDictionary.So add a new UserControl and do the following.

  1. Delete the xaml.cs file
  2. Remove the x:Class attribute from UserControl’s xaml declaration.
  3. Remove the Width and Height properties
  4. Remove the default Grid control.
  5. Change Build action to Resource.
  6. Rename the UserControl XAML tag to ResourceDictionary.

Now the XAMl will look as follows

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
</ResourceDictionary>





To create a new ResourceDictionary using Blend 3 ,go to resources tab.Click on the ‘+’ located at top right to show the creation dialog.Give the name and press ‘OK’.I will be writing another post in detail which describes creation and manipulation of ResourceDictionaries using blend.





Adding resources



Adding xaml elements into ResourceDictionary is same as before.We can add any xaml element including Button,Grid,Brush,Color,Templates,Styles etc…A typical Colors.xaml resource dictionary is shown below




<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Color x:Key="bgcolor">Red</Color>
</ResourceDictionary>





Merging resource dictionaries



ResourceDictionary now got a new property called MergedDictionaries.This is a collection of ResourceDictionaries.We can add any number of ResourceDictionaries into this.Also we can merge a ResourceDictionary into another ResourceDictionary.Below is a Brushes.xaml which uses the Colors.xaml as a merged resource dictionary.




<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Colors.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="background" Color="{StaticResource bgcolor}"/>
</ResourceDictionary>




Now we got brushes.xaml.This can be merged again with UserControl.xaml in order to use the brushes.




<UserControl x:Class="CustomEffects.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Button Grid.Row="1"
Background="{StaticResource background}"
Content="Click to change"></Button>
</Grid>
</UserControl>





Sample can be downloaded from here.

New features in Expression Blend 3 Part 1

Blend 3 has got so many new features.But here I am going to tell some small easy to explain nice features.

  1. Importing from Adobe Illustrator to Blend(*.ai files)
  2. Importing from Adobe Photoshop to Blend (*.psd files)
  3. Pinning support for Toolbox Windows like VisualStudio
  4. FontManager
  5. Auto-naming of interactive elements.
  6. IntelliSense in XAML as well as in CS.
  7. Annotation support.

Importing Adode files : These are just facilities to import vector based .ai files from the Adobe illustrator and psd files from PhotoShop.

Pinning support for ToolBox Windows : Now the toolboxes are same as of Visual studio toolboxes.If we don’t want some toolboxes we can pin them to the respective sides of the window.Pin button is placed same like in the Visual studio(at top right).

Font Manager : Font manager allows us to import fonts and add to our solution.Later we can pack these fonts with our application.

Tools->FontManager

Auto naming interactive elements : This gives name to the interactive elements like Button,Textbox etc.Note that this won’t name the Grid,StackPanel etc..

Tools->Name Interactive Elements

IntelliSense in XAML as well as in CS : It has got IntelliSense support for both XAML and C-Sharp.

Annotation support : Now we can add annotations over the design area of Expression Blend.They are very much useful in describing nature and purpose of visual elements.From my first experiments it seems ,WPF only supports this feature.

Tools->Create Annotation

There are some more new features such as Sample data which help us to show sample data in design time.That will be discussed soon…

Tuesday, March 24, 2009

Silverlight 3 Beta Offline or Out of Browser applications

Now Microsoft added support for Silverlight applications to run out of browser.Earlier it was accomplished by a tool called Desklighter released by Identitymine.

Details on how to make a Silverlight 3 application offline is available here by Pete Brown.

Portability of offline Silverlight applications.

This post describes how can we make the Silverlight applications portable.ie how to copy offline Silverlight application from one system to another.

Normally when we select the Install button on the silverlight context menu the system copies the required files (mainly .xap)into a cache folder locatable at

[Drive]:\Users\[username]\AppData\LocalLow\Microsoft\Silverlight\Offline

The folder name will be localhost.<serial no of offline app in the system> provided the Silverlight application which you saved is running in the localhost.

For eg if you are creating your first offline application the folder name will be localhost.0.

Once you locate this offline folder you can just copy that folder to the new machine.To run the application you need to copy the Shortcut file also which was created in the desktop or in the start menu.In case you don’t have the short cut file you may run by giving the following command in console.

[Install drive]:\Program Files\Microsoft Silverlight\3.0.40307.0\sllauncher.exe" localhost.0

To run another offline application just change the number (here 0) at the end.

NB: This post is written based on Silverlight 3 Beta.Things may change in actual release.

Monday, March 23, 2009

Silverlight 3 Beta Pixel Shader Effects

This is another nice feature included in Silverlight 3.Pixel shaders are programs which operate at pixel level.ie all pixel values(value of A,R,G,B) are passed through the associated pixel shaders before displaying in the screen.Then the pixel shaders will do some calculations and change the pixel value.
For example if we have applied a pixel shader called “Negative” to a StackPanel,then all pixels in the area of that StackPanel will go through Negative pixel shader and it Negate the pixel values by decrementing from 255(255-A,255-R,255-G,255-B).
This is the basic idea of pixel shaders and the Silverlight 3 itself contains 2 Pixel shader effects as of now.They are DropShadow and Blur.

Applying pixel shader Effect

Now the UIElement class in the Silverlight has got a new dependency property called Effect which is the entry point to the pixel shaders.We can directly apply the Effect to this property.Since all the controls and visual elements are inherited from UIElement,they also have the pixel shader support.
Applying DropShadow pixel shader effect through XAML to a Button

<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Joy's Button">            <Button.Effect>                <DropShadowEffect Color="Black"                                  ShadowDepth="5" />            </Button.Effect></Button>
C# to Apply DropShadowEffect


private void Button_Click(object sender, RoutedEventArgs e){    btn.Effect = new DropShadowEffect() { Color=Colors.Black,ShadowDepth=5};}



Grouping pixel shader effects

The Silverlight 3 currently doesn’t support grouping of Effects.If we want to apply Blur effect and DropShadow effect to a Button we have to go for a workaround.
  • Wrap the control using a Border.
  • Apply the new effect to the border.

<Border>            <Button HorizontalAlignment="Center"                    VerticalAlignment="Center"                    Content="Joy's Button">                <Button.Effect>                    <DropShadowEffect Color="Black"                                      ShadowDepth="5" />                </Button.Effect>            </Button>            <Border.Effect>                <BlurEffect Radius="5" />            </Border.Effect></Border>



Blur effect has been applied to the Border in order to get more than one effect on the Button.Writing custom pixel shader effects will be discussed later.

Friday, March 20, 2009

Silverlight 3 Beta ElementToElement Binding

Finally it is released with developer license and available for download here.

It has got so many features.Among them the Element to Element Binding got my attention first.That is the feature which I was waiting from the beginning as I came from WPF background.

What is Element to Element Binding

It is nothing but binding one element’s property to other element’s property.If the properties are of different type we need to employee a converter.

   1: <StackPanel>

   2:             <Slider x:Name="sldr" />

   3:             <TextBox Text="{Binding ElementName=sldr,Path=Value,Mode=TwoWay}"  />

   4:</StackPanel>



Here the Slider is the source and the TextBox is the destination.Whenever the Slider changes the TextBox will get slider’s value and vice versa.
If there is no mode specification the binding will be one way hence the TextBox will get updated as per Slider.But slider will not update as per TextBox.