There's something about WPF

in

November 2007 - Posts

Google Gears on Iphone, Ohh yaa!!

Recently Google announced the Google Gears api which can be used to manage a site data offline. Once the website is in online state, the whole site data will be refreshed with the data that was added while offline. Such a feature is really compelling to me since it happens a lot of times that I have some idea while travelling and need to blog about while fresh in my mind. Google Gears is made purely in  HTML and javascript. That brings me to the talk for iphone. Steve Jobs mentioned about iphone not able to run 3rd party applications on it. But I think it would be really interesting to develop an application using Google Gears for such smart phones without installing any other applications on it. The only caveat is the local storage. Being offline, the data entered in the site has to be stored on the phone somewhere. Cookies, not a good idea since they would be cleared sometimes.

SQLite database(the one I know of) can be accessed perfectly from javascript using Ajax and its also possible to store objects like images and other HTML elements.

I really hope Apple and Google comes up with some storage mechanism on the iphone which would allow developers to really create applications which can be "online while offline".

Using IDLoginView with IDLogin

The IDLoginView control shipped with the Windows Live Tools control is a pretty good control for developers who want to customize the web page look depending on the Sign In status of the user. Normally, you would use a Login control on the page and once signed in with it, you could write a piece of code to display some items on the page which you want to display only to Windows Live Signed In users. Even more, if you plan to use ASP.NET Forms authentication for your website and customize the display for the users after being authenticated with it, you would write your own code to display them. IDLoginView control takes a step ahead and makes it way easy for the developer to assign templates depending on the status of the user visiting the page.

The IDLoginView control has 5 templates defined as follows:

  • Anonymous : Not signed in Windows Live and not authenticated by ASP.NET website
  • Loggedin : Authenticated by ASP.NET but not signed in Windows Live.
  • LoggedInId : Signed in Windows Live
  • LoggedInAll : Signed in Windows Live and ASP.NET website.
  • AssociatePrompt : A template used to prompt the user to associate the windows live ID with the ASP.NET user account.

The templates are self-defined here but the interesting one is the Associate Prompt. This prompt if defined for the control, will prompt the user whether to create an association between their windows live account and ASP.NTE website account. Of course for this template to appear one has to create a website account using the ASP.NET security configuration. Once an association is created, any time later if the user signs in Windows Live they will be automatically authenticated for the ASP.NET website.

Follow the following simple steps to use these controls on your page.

  • Drag a IDLoginView control on the page. In the designer view, click the small arrow button over the control to view all the templates.
  • Drag a ASP.NET Login control and the IDLogin control in this template.
  • Since you would need to see the status of the user all the time, copy these Login and IDLogin control in all the templates.
  • The AssociatePrompt template displays a message with Yes and No buttons. You could change this template as you want, but make sure that there is a button which has a command name as associate_yes and another button with a command name as associate_no.

You could test your application by running the website and signing in Live and ASP.NET website. The prompt appears when you are signed in one of the accounts and then sign in the other account. To this to work you need the PromptOnAssociation to true.

Internally when you give an affirmative response to the prompt, a single row is added in the aspnet_LiveIDAssociation table in ASPNETDB database. You can see this database if you do show all files for the project. If you no longer want this association to take place delete this row from the table, for now, there is no UI to remove the association for the control.

I avoided thorough details about the control since you can find them here.

 

Cannot Open User Default database Error.

Bug: If you open the table to view the association entry, and then again try running the website you might get an error like Login failed for the default user. This bug is been posted on ASP.NET forums and many other places. I tried closing the IDE and reopening it. The website works, I think this is a bug with the SQL express since when it is open in the IDE, the error appears.  

 

 

Custom PowerShell Cmdlets

Command line tools have always been my favorite, whether its a linux box or a windows machine. Its way cooler!! (don't know why). I use Powershell on Windows Vista and I really like for the fact that its designed in .NET environment which makes it easy to extend as you want. I am assuming you have basic information about Cmdlet and Snap-In classes for Powershell. If not, please refer to the the documentation which comes with Powershell installation.

I wanted a simple program to run in Powershell to display the temperature given the zipcode. I am going to show you how easy it is to add a new command in Powershell. A command like dir, ls etc. is called as a Cmdlet in Powershell. To use a new command in Powershell you need to do the following:

1) Create a .NET class which inherites from PSCmdlet. Add the functionality as required. This will be the custom Cmdlet class.

2) Create a new class in same namespace as the above class. The base class for this class should be PSSnapIn. This will be the custom Snap In class which is required to insert any Cmdlet in Powershell. 

3) Register the Cmdlet using the SnapIn class we created.

That's it!!

Creating a Custom Cmdlet class

Nothing makes it more clear than a piece of code right. Here it goes!

using System.Management.Automation;
using System.Management.Automation.Provider;

[Cmdlet(VerbsCommon.Get,"temp")]
    public class TempCmdlet : PSCmdlet
    {
        private string zip="60606";
        [Parameter(Mandatory=false,Position=0)] 
        public string ZipCode
        {
            get
            {
                return zip;
            }
            set
            {
                zip = value;
            }
        }

        public object[] GetData()
        {           
            Service1 service = new Service1();           
            object[] data = service.GetWeather(ZipCode);
                return data;
        }

        protected override void ProcessRecord()
        {           
            object[] data = GetData();
            if (data.Length == 3)
            {
                WriteObject("Location : " + data[0].ToString());
                WriteObject("Condition : " + data[1].ToString());
                WriteObject("Temperature : " + data[2].ToString()+ " F");
            }         
        }
    }

This is my custom Cmdlet class. Observe the attribute to the class. This attribute shows that the command I would issue at the prompt would be Get-temp. The first part has to be a predefined verb in the VerbsCommon definition. The second part could be anything meaningful to you.

I am using a webservice to get the weather data by passing a zipcode to it. By default its 60606. Of course you could use a data store for the same thing. If you need any parameters to your Cmdlet you should create a Property and assign an attribute called Parameter. There are a bunch of values for this attribute but I used some common ones. The important function to look out is the ProcessRecord. This function is executed when the user invokes the Cmdlet at the prompt. Writeobject function  actually writes the data to the output pipeline which is displayed to the user. There are several other functions which can be effectively used to improve the output but I did not go in that detail.

Creating a SnapIn class.

To register the Cmdlet , you need a custom SnapIn class. Here it goes again.

[RunInstaller(true)]
    public class TempSnapIn : PSSnapIn
    {
        public TempSnapIn() : base()
        {
        }

        public override string Name
        {
            get
            {
                return "TempSnapIn";
            }
        }

        public override string Vendor
        {
            get
            {
                return "Microsoft";
            }
        }
        public override string VendorResource
        {
            get
            {
                return "TempSnapIn,Microsoft";
            }
        }

        public override string Description
        {
            get
            {
                return "This is a PowerShell snap-in for the Get-temp cmdlet.";
            }
        }

        public override string DescriptionResource
        {
            get
            {
                return "GetTempSnapIn,This is a PowerShell snap-in for the Get-temp cmdlet.";
            }
        }
    }

Make sure you override all these properties, if not you would get some error when you try compiling this class. Place this class in the same namespace as the Cmdlet. Although I am not sure if different namespaces would work but you can try that.

Register the Cmdlet

We are ready to register our little Cmdlet created. This is the mose exciting part since we need to hit some commands in Powershell. Yessssssss!!

Open Powershell prompt.

Give the following commands.

PS> $ref = "$Env:ProgramFiles\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll"
PS> $compiler = "$env:windir/Microsoft.NET/Framework/v2.0.50727/csc"
PS> &$compiler /target:library /r:$ref Codefile.cs 

Codefile.cs should be the .cs or .vb file for your classes. This is the step to compile the code, you could obviously use the IDE to do this step.

Now to actually register the Cmdlet, use the InstallUtil program.

PS>set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil
PS> installutil Codefile.dll

Replace the Codefie.dll with your dll created in earlier step.

Now add the Snap In we created to the shell

PS>add-pssnapin SnapInclassname
We are done!! You could check by doing Get-temp at the prompt. Do not close the windows since you would lose all the settings you just did. Instead to save the session export the console as below.
PS> export-console MyCustomShell

If you have any particular questions about the code or anything else please reply to this post.

Integrating Windows Live Authentication in your Website


This week Microsoft launched Windows Live Tools for Visual Studio 2008 and Visual Web Developer Express. Its been an exciting experience for me to work on this project. Since I worked on these controls, I thought of sharing my ideas with you about effectively using these controls in your website. I would specifically focus on IDLogin and IDLoginView controls.


1)      Download the Windows Live Tools installer from here. The dll’s are installed in Program Files/Windows Live Tools/ directory. Once installed a new tab of Windows Live Tools is created in the Visual Studio toolbox which contains the Live controls.


Design View errors in visual studio

Since Visual Studio 2008 is in beta stage there might be different experiences depending on the configuration of the machines. For some reason if you have problems seeing these controls in the toolbox or there is an error in the design view saying error creating control or something like that, close the IDE, open the visual studio command prompt and issue a command devenv /setup. This will reset IDE environment and possible get rid of the errors.

 

2)      Open Visual Studio 2008 and click New Website. Here you would find a new website template called ASP.NET Windows Live Website. This template has all necessary settings for running Windows Live controls on a page. If you don’t want to use this template for some reason, make sure you have necessary settings on your existing website before using the controls.

For IDLogin control first add a Script Manager to the page since the IDLogin control is an Ajax server control and uses an Update Panel internally to do asynchronous postbacks. IDLoginView has to specific requirements. For specific requirements for Silverlight Media  and Contacts control please refer to the Live website here.


Using IDLogin for Windows Live Authentication


This control can be used to authenticate users with their Windows Live ID account. This account is same account used for passport authentication.

Drag the IDLogin control on the page. This control needs a Live Application ID and Secret Key. To get this, click the action list button (little arrow button)on right top control of the control in the designer view.

Click the Create new Application ID link which opens a browser control. Click register an application and fill the details. After submitting those details an Application ID is provided by Windows Live which is unique to your application. Escape key closes the window.

The new Application ID and Secret is stored in an Appsettings section in your web.config file. The control uses this section all the time to authenticate your application so do not delete this section.


If you already have a registered application, paste the Application ID in the value field for wll_appid key and Secret in the value field for the wll_secret key. Save the Web.config file.

The control is ready to go live :). Run the website, a SignIn link is displayed on the page which when clicked takes the user to the Windows Live login page.

The control supports two client side events as OnClientSignIn and OnClientSignOut and two server side evens OnServerSignIn and OnServerSignOut. Further information about these events can be found here.


Important points to remember:

After Windows Live redirects to the return url you provided, the IDLogin control performs a redirect to itself. This is done to avoid firing of the sign in and sign out events every time a page refresh is done by the user. Thus you need to be aware of this fact that a redierct is happening because of the control which you might want to handle in your code. Ill post more such points if I come across while I continue working on them.

Make sure you read the Known Issues section on this link. These issues would be resolved in later releases of the controls.

In the next post I will show how to use IDLogin and IDLoginView control to effectively use ASP.NET membership account and Windows Live account and create associations between them.

Ajaxifying the Web


Web based Chat with Ajax


Having a little chat window with a list of friends connected in the chat room is awesome! But the important thing is it should not be at the expense of the overall performance of the website. I created a website with other silverlight stuff on it and this Chat area as a side thing. I have used the ASP.NET Ajax framework which is pretty simple to use.

Follow the steps and at the end you would be enjoying a chat area on a web page.


Step1 : Creating the Chatter List

Drag a Script Manager on an ASP.NET page. If you create an ASP.NET Futures website, a script manager is already present.

 Drag an UpdatePanel  on the page and name it,say, chatterUpdatePanel. Drag a ASP.NET listbox control in the Update Panel. Behind the scenes a contenttemplate tag is created under the Update Panel. This is the area for the chatter names which will get update asynchronously.

I thought of having some basic authentication required before chatting. So I created a username and password textbox and a Sign In button outside the Update Panel. The click event of the Signin button must update the chatter listbox. To do this we need to specify a trigger to the update panel.


<asp:UpdatePanel ID="chatterUpdatePanel" UpdateMode="Conditional" runat="server">            

                  <ContentTemplate>

                  <div id='hello' style="overflow:auto;width:146px"  >

                      <asp:ListBox ID="listChatters" runat="server" Height="180px" Width="200px"

                          BackColor="White" Font-Names="Verdana">

                      </asp:ListBox>

   </div>                                                                                                                                                          

                  </ContentTemplate>

                  <Triggers>               

                  <asp:AsyncPostBackTrigger ControlID="ChatterTimer" EventName="Tick" />    

                  <asp:AsyncPostBackTrigger ControlID="signin" EventName="Click"/>                                                                                           

                  </Triggers>

            </asp:UpdatePanel>

 


The signin controlID is the Sign In button I used for signing in users. You can see another trigger with the control ID of ChatterTimer. Now if some friend of yours signs in at his house, everyone needs to know he signed in so I update the chatter listbox every 10 seconds. For this drag a ASP.NET Timer control on the page outside the update panel. Add a Async trigger to the chatterupdate panel with the event name as “Tick”. Thus every 10 seconds the listbox is updated without refreshing the whole page. 

 


Step 2 : Creating the Messages Listbox 

To display messages that are being sent, I use a listbox control. This listbox has to be updated independently of the Chatterlistbox. For this drag another Update Panel on the page and add a listbox in it. Call it say MessagesUpdatePanel.

There has to be an area where a chatter can type his statements and send them. I created a textbox and a button “Send” under the messages listbox. Make sure these two controls are outside the MessagesUpdatePanel. Add an async trigger to this update panel with controlid of  the Send button and the event name as Click. Also since the messages come more frequently an update is required in a lesser interval. So drag a timer control and assign interval of 1 second and add an async trigger to the MessagesUpdatePanel with the control id of this timer control and event name “Tick” as follows:


<asp:UpdatePanel ID="messagesUpdatePanel" UpdateMode="Conditional" runat="server">            

              <ContentTemplate>

              <asp:Label runat="server" Text="" ID="labelWelcome" ForeColor="#006699"></asp:Label>

                  <asp:ListBox ID="listMessages" runat="server" Height="280px" Width="392px"

                      BackColor="Black" ForeColor="limegreen" Font-Names="Verdana">

                  </asp:ListBox>                                                                                                

              </ContentTemplate>

              <Triggers>              

              <asp:AsyncPostBackTrigger ControlID="sendButton" EventName="Click" />

              <asp:AsyncPostBackTrigger ControlID="ChatTextTimer" EventName="Tick" />              

              </Triggers>

             </asp:UpdatePanel>




 Please be aware that the textbox which would be used to type statements must be outside the update panel since we do now want to update anything in it.



Step 3 : Storing chat data.            

Now since we have the desig ready we need to have a way to store the chatters which have valid accounts. Also for my website I display the latest 10 messages in the messages listbox just for the heck of it I think :).  I added a Global.asax file  to my project to manage application level data. I have created a List<> of chatters in the global.asax.cs file as follows:

List<Users> chatters = new List<Users>()

        List<string> messages = new List<string>();

 

In the Application_Start event I do the following:

 

 

Application.Add("chatters", chatters);

            Application.Add("chats", messages);

 

 

Now since the Application object can be accessed in the Page too, I add any user which is created on the site into this list. Also as a messages is sent I add it in the messages list.

In the Page_Load event I load the chatters and the messages in the respective listboxes.

Following is a simple way to display List items in a listbox

List<string> messgs = (List<string>)Application["chats"];

            listMessages.DataSource = messgs;

            listMessages.DataBind();

Similar procedure can be followed for chatter listbox too.

Some cool stuff!!

I am working on building a website consisting of some “cool stuff” using some of the Microsoft features like Silverlight and ASP.NET Ajax. I have pretty simple but handy chat on the web using update panel control. I think with the same structure multiple chat rooms can be built. I also made a customized listbox in Silverlight. The listbox can be modified as you want just by putting in some extra code.



Custom Silverlight ListBox


I have used the Listbox control provided in the Silverlight.Samples.Controls.dll which is located in the Silverlight 1.1 installation directory. The complete path might look like this

 C:\Program Files\Microsoft Silverlight 1.1 SDK Alpha Refresh Sept 2007\Tools\SilverlightControlsStarterKit\SilverlightUIControls\ClientBin

To get this path, you would have to build the project file in the directory. Sometimes Visual studio does not allow to reference a dll which is hidden under many diectories. If you add a reference to such a dll you might get an error like the reference path is too long. So copy the dll into your project Bin directory and then add a reference to it. There is a small bug in this Listbox control which was mentioned and fixed as per Vivek Dalvi’s blog. Find the UpdateLayout function in the Listbox.cs file and locate the

Clip = clip;

statement. Replace this by ActualControl.Clip = clip; That’s it. I should have told you this before asking you to reference the dll :).

Now is the time to create items which could be added. The ListBox.Items.Add accepts parameter of FrameworkElement. So the default xaml controls could be added to it but I have not tried all of them. I created a custom control to be added as an item to the listbox. I wanted to display textblocks with rounded corners inside this listbox.  To begin with add a Usercontrol item to a Silverlight project. You could see in its code-behind a class inheriting from Control class is generated and some logic in its contructor. Observer the first line.


Stream s = this.GetType().Assembly.GetManifestResourceStream("Silverlightanim.BlogItem.xaml");


To successfully run the GetManifestResourceStream function the item which is given in the string must be marked as an Embedded Resource. If not, you might not get an error but it is just not executed. Following is the xaml code for the BlogItem which I add in the listbox.

 

<Canvas

      xmlns="http://schemas.microsoft.com/client/2007"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      x:Name="UserControl"

      Width="600" Height="110" Canvas.Left="4.5">

      <Rectangle Width="600" Height="110" Stroke="#FF000000" RadiusX="10.5" RadiusY="10.5">

                        <Rectangle.Fill>

                              <LinearGradientBrush EndPoint="0.503,-2.107" StartPoint="0.497,3.107">

                                    <GradientStop Color="#FF000000" Offset="0"/>

                                    <GradientStop Color="#FF2F1D1D" Offset="1"/>

                                    <GradientStop Color="#FF16657C" Offset="0.019"/>

                              </LinearGradientBrush>

                        </Rectangle.Fill>

    </Rectangle>       

    <TextBlock x:Name="content" Width="598" Height="88" Text="" TextWrapping="Wrap" Foreground="#FFC3C3C3" FontFamily="Verdana" FontSize="12" Canvas.Left="9" Canvas.Top="10"/>

</Canvas>



Its really nothing heavy, its just has a rectangle with rounded corners and a textblock . Following is the code-behind file.


namespace Silverlightanim

{

    public class BlogItem : Control

    {

        Canvas rootCanvas;

        TextBlock block;

 

        public BlogItem()

        {

            Stream s = this.GetType().Assembly.GetManifestResourceStream("Silverlightanim.BlogItem.xaml");

            rootCanvas = (Canvas)this.InitializeFromXaml(new StreamReader(s).ReadToEnd());

            block = (TextBlock)rootCanvas.FindName("content");

            this.Height = rootCanvas.Height;

            this.Width = rootCanvas.Width;           

        }

              

        public string BlogContent

        {

            get

            {

                return block.Text;

            }

            set

            {

                block.Text = value;

            }

        }

    }

}




As you see a public property has been declared which sets the text property of the textblock. 

Now the final act of using the listbox and this blog item control on a silverlight page. For my project I am getting the data from an xml file which makes it easier to maintain later. Here is a sample xml file


<?xml version="1.0" encoding="utf-8" ?>

<ContentList>

  <Block Content="Hey John!!"></Block>

  <Block Content="Hey Jerry!!"></Block>

  <Block Content="Hey Nick!!"></Block>

  <Block Content="Hey Peter!!"></Block>

  <Block Content="Hey Charlie!!"></Block>

</ContentList>



I would not go in detail explaination for the following code since its all obvious. It is the code-behind for the Page.xaml file.

 

 

Using Silverlight.Samples.Controls;

ListBox list;

public void Page_Loaded(object o, EventArgs e)

        {

            // Required to initialize variables

            InitializeComponent();           

           

            InitializeList();

        }

 

  void InitializeList()

        {

            System.IO.Stream str = this.GetType().Assembly.GetManifestResourceStream("Silverlightanim.Data.xml");

            //Initialize Listbox

            list = (ListBox)this.FindName("listbox");           

            XmlReader xr = XmlReader.Create(str);           

            while (xr.Read())

            {

                if (xr.IsStartElement("Block"))

                {

                    BlogItem item = new BlogItem();

                    item.BlogContent = xr.GetAttribute("Content");

                    list.Items.Add(item);

                }

            }

           

            list.UpdateItems();

        }

 

Make sure that the xml file is marked as an Embedded Resource and give its complete resource name i.e. namespace.Data.xml  for the GetManifestResourceStream function to work. You might have to adjust the width and height properties of the listbox to fit in the items.

WPF Basics

Recently I have been working part time on a card game (simplified version of poker) using WPF. I had built some 2D games using Windows forms earlier but let me tell you, WPF is picture perfect for such applications. I have used Expression Blend for designing the game and Visual Studio 2008 for the code behind logic. (That’s a killer combination!). I would point out some important things which I feel WPF beginners would face while building a 2D game.

WPF Animation in code-behind

 A 2D game made in WPF with no animation is hard to imagine to me. Expression Blend facilitates with hooking up events to a particular timeline(animation) created.  But several times we might need to animate things in the code-behind. Here is a way to do it which I use a lot of times in my code.

   C#

   Storyboard story1 = (Storyboard)FindResource([key]);

   Story1.Begin(this);

 

That was easy.  

 

Mixing Windows forms with WPF forms.

 

Since I had few windows forms developed earlier which would be useful in this game, I thought of starting the application with a already existing windows form. This is not that difficult. A WPF application starts from the Main function located in the App.g.cs file (if C# environment) which is at the path projectrootdir/ obj/Debug. This Main function instantiates an object of class App,which is inherited from Application class, and runs it. The App.xaml file contains a StartupUri property to set the start form. Remove that property and a set an eventhandler for the Startup event of App class. In this event handler one can instantiate a form object as needed.  The Application xaml tag looks somewhat like this:

 

<Application x:Class="MiniPoker.App"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Startup="Application_Startup">

     <Application.Resources>

      

    </Application.Resources>   

</Application>

I will be continuing this blog in later posts diggin into more complex parts. Be in touch.