Silverlight Introductory Session at NUST Islamabad

7th May Saturday, i went to NUST islamabad to conduct an introductory seminar for Microsoft Silverlight. Organized by Microsoft Pakistan, it was the first event at NUST with hopes to have more detail sessions in coming educational session.

Resource Loading Order

In WPF we are familiar with resources, as we heavily use it for styling and bindings. I tried a few stuff while i was examining the order of resource rendering and allocation to a control. I created a style with a SolidColorBrush and add it in app.xaml, Window.Resources, and set the color to Red and Green.

Style was like this

<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
</Style>

I applied the resource to a TextBlock Foreground Color property like below

<Textblock x:Name="Title" Text="Hello World" Foreground="Red"/>

What happened was that the textblock picked the color from app.xaml file. That means the resource sequence is from local resource to global or inside to outside. A good tip for the WPF stylists. Hope it helps.

Some words about Silverlight

Silverlight is a remarkable web technology, its a tough and a little above the edge to Macromedia Flash. I thought of not comparing it, but i worked on flash as well, and it seems that flash is also not so far behind in database programming, network sockets, consuming web services, and obviously king of crispier web animation and graphics. So where does silverlight comes in.

Silverlight has lot more to do with web than other technologies. I like the statement i read somewhere that it is targetted towards the developers. I as a developer first started silverlight and thought it is more like animation stuff. But soon i saw the magical things like superb databinding modes, MVVM, Ria Services, controlled architecture, screaming vector graphics, hardware support, and all in all  support to program in my favourite technology C#. Its been six months, and i can say ‘ I’m loving it”.

I will also comment on few things which goes a little negative towards my favourite tech. I once recommended to a buddy in USA to develop a site in silverlight. He thought it would be a good idea, but later on, he came to know that his hosting does not support .net 4, entity framework and LINQ. So guys with hosting support till .net 2.0 will suffer a lot. Also, the Entity framework model was not well mature, and it had some nitty gritty flaws. Which if we fancy doing stuff in latest technology we can do it for show off, but in real world i believe we should stick to the ground realities as well.

Silverlight close beta version 5 is out. Looking forward to see the power in it. But on the contrary, i see microsoft being focusing on HTML 5 for its IE9 compaign at MIX 11. This was strange to see. As we know HTML 5 is a growing competitor to silverlight, as it also has features like hardware rendering, canvas, isolated storage, local database, and lot more in offerings.

I foresee technological war ahead, already developers are fed up of browser war, not we see technology wars. I think developers will have to make hard choices in near future about choosing between web frameworks and technologies.

Silverlight Spinner Control

Hey guys, i am a silverlight developer. I had a requirement to use a spinner control. Ohh, what? its not in Silverlight toolkit, wow man, Microsoft Silverlight do not have Spinner control, while in WPF we have it.
After banging my head to google walls instead of microsoft windows, i decided to make my own.
It was quiet simple. Here is the xaml code:
Create a new file named Spinner.xaml as a Silverlight/WPF UserControl. Code is as below:
XAML
<UserControl x:Class=”Devbridge.Controls.Spinner”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006
xmlns:d=”http://schemas.microsoft.com/expression/blend/2008
mc:Ignorable=”d” Loaded=”UserControlLoaded” >
<Grid Background=”Transparent”>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width=”20″></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox MaxLength=”4″ Grid.RowSpan=”2″ IsHitTestVisible=”false” Background=”Transparent” VerticalContentAlignment=”Center”
HorizontalAlignment=”Stretch” VerticalAlignment=”Stretch” Foreground=”White” x:Name=”txtSpin”/>
<Button Content=”p” Grid.Row=”0″ Grid.Column=”1″ FontFamily=”Wingdings 3″ FontStretch=”Normal”   HorizontalAlignment=”Stretch” VerticalAlignment=”Stretch” x:Name=”btnUp” Click=”btnUp_Click” />
<Button Content=”q” Grid.Row=”1″ Grid.Column=”1″ FontFamily=”Wingdings 3″ HorizontalAlignment=”Stretch”  VerticalAlignment=”Stretch” x:Name=”btnDown” Click=”btnDown_Click”/>
</Grid>
</UserControl>
C#
using System.Windows;
using System.Windows.Controls;
namespace Devbridge.Controls
{
///
/// Interaction logic for Spinner.xaml
///
public partial class Spinner : UserControl
{
public Spinner()
{
InitializeComponent();
}

private double _spinnerVal;
public double SpinnerVal
{
get { return _spinnerVal; }
set { _spinnerVal = value;
txtSpin.Text = _spinnerVal.ToString();
}
}
private double _spinnerValMin;
public double SpinnerValMin
{
get { return _spinnerValMin; }
set { _spinnerValMin = value; }
}
private double _spinnerValMax;
public double SpinnerValMax
{
get { return _spinnerValMax; }
set { _spinnerValMax = value; }
}
private double _spinnerFactor;
public double SpinnerFactor
{
get { return _spinnerFactor; }
set { _spinnerFactor = value; }
}
private void UserControlLoaded(object sender, RoutedEventArgs e)
{
SpinnerValMin = 0.5;
txtSpin.Text = SpinnerVal.ToString();
}
private void btnUp_Click(object sender, RoutedEventArgs e)
{
if(SpinnerVal+SpinnerFactor = SpinnerValMin)
{
SpinnerVal = SpinnerVal - SpinnerFactor;
txtSpin.Text = SpinnerVal.ToString();
}
}
}
}
<my:Spinner x:Name="DevSpinner" SpinnerFactor="0.5" SpinnerVal="0.5" SpinnerValMax="10" SpinnerValMin="0.5" Height="33" Width="44" />
Rules:
- To get value of spinner text you will use SpinnerVal property
- User will not be able add value lower than SpinnerValMin
- User will not be able to enter value greater than SpinnerValMax
- To add the value increment or decrement factor we will use SpinFactor property
I hope the fellows who keep banging there heads on Google walls, can now get a better solution to there problem.

WPF UI Automation using WebBrowser Control and WebClient

One smart day i was sitting on my seat and was feeling the fresh air, when i got an email about developing a Proof of concept for a upcoming project. I felt like a super hero as it was like saving the day from monsters and Alien Laser guns. Jokes apart, i was tasked to download a file from a website. Simple isn’t it, but i do not have to do it through mouse and keyboard, my application should go to website, login to website, click some links, navigate automatically through pages, reach the specific download page, initiate the download request and save the file to some place.
Requirements :
– Development platforms can be Silverlight, WPF or windows
– Should go to a website say http://www.gmail.com
– Login to an account
– Click Inbox
– Find emails with attachments
– Download Attachement
Development Phase:
I started to develop it in Silverlight as i was provided with a sample UI and some implemented code in Silverlight. Soon i came to know that in Silverlight we do not have much support for DOM processing. I decided to develop in WPF. I thought of a new scenerio that is below:
– Go to telerik.com
– Login to site
– Move to free tials page
– Download MVC package from the list

My User interface looked like below:

XAML
<Window x:Class=”WebBrowserAutomationWPF.MainWindow”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
Title=”MainWindow” Height=”350″ Width=”525″ Loaded=”Window_Loaded”>
<Grid>
<WebBrowser HorizontalAlignment=”Stretch” Name=”webBrowser1″ VerticalAlignment=”Stretch” Margin=”0,38,0,0″ />
<Button Content=”Idle” Height=”23″ HorizontalAlignment=”Left” Name=”showHtml” VerticalAlignment=”Top” Width=”186″ Click=”showHtml_Click” />

</Grid>
</Window>

It has a Web Browser control and a Button. I am using the button for showing the progress only, nothing fancy.
On Windows loaded event i ask it to move to http://www.telerik.com/ and also subscribe to two events which will become handy as we go on.

C#
private void Window_Loaded(object sender, RoutedEventArgs e)
{
webBrowser1.Navigate(new Uri(“http://www.telerik.com/“));
webBrowser1.LoadCompleted += new LoadCompletedEventHandler(webBrowser1_LoadCompleted);
webBrowser1.Navigating += new NavigatingCancelEventHandler(webBrowser1_Navigating);
}

In Load completed event i switch each page with a flow id, so on each navigation event i process something different to navigate further.

C#
void webBrowser1_LoadCompleted(object sender, NavigationEventArgs e)
{
mshtml.HTMLDocument doc = (mshtml.HTMLDocument)webBrowser1.Document;

if (flowid == 1)
{
IHTMLElementCollection theElementCollection;
theElementCollection = doc.getElementsByTagName(“input”);
foreach (IHTMLElement curElement in theElementCollection)
{
if (curElement.getAttribute(“name”, 0) != null && curElement.getAttribute(“name”, 0) != String.Empty)
if (curElement.getAttribute(“name”, 0).StartsWith(“ctl00$YourAccount$tm_usercontrols_public_clientnet_loginnameandstatus_ascx1$btnLogin”))
{
curElement.click();
}
}
}
else if (flowid == 2)
{
IHTMLElementCollection theElementCollection;
theElementCollection = doc.getElementsByTagName(“input”);
foreach (IHTMLElement curElement in theElementCollection)
{
if(curElement.getAttribute(“name”, 0)!=null)
if ((curElement.getAttribute(“name”, 0).ToString() == “ctl00$PageContent$usercontrols_public_clientnet_signinform_ascx5$loginForm$UserName”))
{
curElement.setAttribute(“Value”, “<Your loginid email here >”, 0);
}
else if ((curElement.getAttribute(“name”, 0).ToString() == “ctl00$PageContent$usercontrols_public_clientnet_signinform_ascx5$loginForm$Password$tbSanitized”))
{
curElement.setAttribute(“Value”, “<Your password here>”,0);
}
//else if ((curElement.getAttribute(“name”, 0).ToString() == “ctl00$PageContent$usercontrols_public_clientnet_signinform_ascx5$loginForm$RememberMe”))
//{
//    curElement.setAttribute(“checked”, true, 0);
//}
}
theElementCollection = doc.getElementsByTagName(“input”);
foreach (IHTMLElement curElement in theElementCollection)
{
if(curElement.getAttribute(“name”, 0) !=null)
if (curElement.getAttribute(“name”, 0).Equals(“ctl00$PageContent$usercontrols_public_clientnet_signinform_ascx5$loginForm$LoginButton”))
{
curElement.click();
}
}
}
else if (flowid == 3)
{

IHTMLElementCollection theElementCollection;
theElementCollection = doc.getElementsByTagName(“a”);
foreach (IHTMLElement curElement in theElementCollection)
{
if(curElement.getAttribute(“innerText”, 0)!=null)
if (curElement.getAttribute(“innerText”, 0).Equals(“Free Trials”))
{
curElement.click();
}
}

}
else if (flowid == 4)
{
IHTMLElementCollection theElementCollection;
theElementCollection = doc.getElementsByTagName(“span”);
foreach (IHTMLElement curElement in theElementCollection)
{
if (curElement.getAttribute(“innerText”, 0) != null)
if (curElement.getAttribute(“innerText”, 0).Equals(“Download Open Source Version”))
{
curElement.click();
}
}

}
else if (flowid == 5)
{
IHTMLElementCollection theElementCollection;
theElementCollection = doc.getElementsByTagName(“a”);
foreach (IHTMLElement curElement in theElementCollection)
{
if(curElement.getAttribute(“title”, 0) !=null)
if (curElement.getAttribute(“title”, 0).Equals(“Telerik.Web.Mvc.Examples-Razor_OpenSource.zip”))
{
downloadfile((curElement as IHTMLAnchorElement).href);
}
}
}

flowid += 1;
}

Here is the download file function:

C#
private void downloadfile(string path)
{

client.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
client.CookieContainer = cookies;
client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
showHtml.Content = “Downloading .. “;
client.DownloadFileAsync(new Uri(path), @”C://web.zip”);
NavigationPath = path;

}

I used webclient to download the file, the problem was to execute the whole procedure silently, so i used webclient else i could have used WebBrowser1.Navigate(((curElement as IHTMLAnchorElement).href); and it would have open a dialog.
The issue arise here, webclient and webbrowser do not share the same session. When we attempt to download the file, through webclient it redirects internally to the login page. And what we get downloaded in web.zip is infact the login.html page. To prevent it, we need to find a way to syncronize the cookie container of webclient and webbrowser document.
I searched a thousand blogs, hundreds of articles, but i seemed it required the Super Hero Magic to do the trick. I keep on hitting the monster, from left, from right, from up and down. And suddenly the monster was defeated and was lying flat in front of me.
The magic was making the webclient CookieAware and using the webbrowser’s navigating event. Webbrowser Only release the cookie container in its event arguments of navigating event. So here is what i did.
C#
public class CookieAwareWebClient : WebClient {

public CookieAwareWebClient() { CookieContainer = new CookieContainer(); }
public CookieContainer CookieContainer { get; set; }
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = CookieContainer;
}
return request;
}
}

And for navigating event;

C#
public CookieContainer GetCookieContainer()
{
CookieContainer container = new CookieContainer();

foreach (string cookie in ((mshtml.HTMLDocument)webBrowser1.Document).cookie.Split(‘;’))
{
string name = cookie.Split(‘=’)[0];
string value = cookie.Substring(name.Length + 1);
string path = “/”;
string domain = “.telerik.com”;
container.Add(new Cookie(name.Trim(), value.Trim(), path, domain));
}
return container;
}

void webBrowser1_Navigating(object sender, NavigatingCancelEventArgs e)
{
cookies=GetCookieContainer();
}

The tricky part with telerik.com was that, along with cookie it requires another string, “Application=1;” so we need to ammend it with the cookie, manually and add in the container.
That was how i lived the day of a super hero and defeated a bunch of monsters. I hope these superhero tricks will help the upcoming heroes to take up such tasks with ease and less research. The whole time i spent was fighting with the webbrowser and webclient to plug-in togther. What i achieved was that webclient by nature is not cookie aware, so first we need to make it cookie aware, and second most important thing is that webbrowser only disclose its cookie container in its navigating event. These two things make life easier, and sky is the limit as we can make scrappers, ui automation tools, Ui testing tools out of it. Hope this will help the people who need this functionality in there application. Thankyou All.

Spoke at event at Air University

I was called by Microsoft Innovation center Karachi to speak at Air University Islamabad. I had to present Microsoft Silverlight technology in front of them. It was a fabolous event. I spoke over Microsoft Silverlight technology, some background, some new features in Silverlight 5, demostrated some code. The students were excited to see the possibilities in Silverlight specially its 3d features, the perspective 3d, augmented reality. I felt that after this event i raised a light in hearts of few young men and that light is Silver.

Ali Sufyan - Speaking at Air University Islamabad