Infosys Microsoft Alliance and Solutions blog

« February 2007 | Main | April 2007 »

March 27, 2007

WPF - Animate with less code

I have been playing around with Animation features of WPF and it has indeed made life easy for developers to build some cool animations quickly. Even if you don't go the extent of using Expression Studio to build complex animations, basic things can be easily done with WPF, XAML and code behind itself.

Whatever animation logic we write in XAML, we can write in code behind also. Though in code behind, this takes lot more lines of code and isn't that easily readable and understandable as it is XAML. In one of the samples that I was building, I had a requirement to animate a control, based on some existing data values.

This meant that I could not do a simple Event trigger implementation in XAML to get the animation going and had to work in the code behind. Without getting into too many complexities of my application, let me give a simple scenario here of animating width and height of a button control. To do this in code behind, the code will look something like this

        private void AnimatorClick(object sender, RoutedEventArgs e)
        {
            DoubleAnimation db = new DoubleAnimation();
            db.From = 100;
            db.To = 300;
            db.AutoReverse = true;
            db.RepeatBehavior = RepeatBehavior.Forever;
            db.Duration = new Duration(TimeSpan.FromSeconds(2));

            DoubleAnimation db1 = new DoubleAnimation();
            db1.From = 50;
            db1.To = 150;
            db1.RepeatBehavior = RepeatBehavior.Forever;
            db1.AutoReverse = true;
            db1.Duration = db.Duration;
           
            Storyboard story = new Storyboard();

            story.Children.Add(db);
            Storyboard.SetTargetName(db, btn.Name);
            Storyboard.SetTargetProperty(db, new PropertyPath(Button.WidthProperty));

            story.Children.Add(db1);
            Storyboard.SetTargetName(db1, btn.Name);
            Storyboard.SetTargetProperty(db1, new PropertyPath(Button.HeightProperty));
           
            story.Begin(this);
        }

I can elimate the .From settings since I want to animate from existing size. This code has taken quite a few lines and animation logic is not even close to being complex. If I start to play around with more complex animation logic like say with Key frame animation, the lines of code will quickly shoot up. Fortunately, ability to call XAML resources in code behind can help with this issue.

Lets add the StoryBoard as a resource to the XAML file. This will be something as below

<Window.Resources>
    <Storyboard x:Key="TestAnimation">
        <DoubleAnimation To="500" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="btn" Storyboard.TargetProperty="Width"/>
        <DoubleAnimation To="350" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="btn" Storyboard.TargetProperty="Height"/>
    </Storyboard>
</Window.Resources>

Now we will use the TryFindResource API to pick the resource from XAML and use in the code behind. We can use the FindResource API as well, but it will throw an exception if the resource isn't found and dealing with exceptions becomes performance draining. .NET has introduced a few similar Try type of APIs (TryGetValue, TryGetArrayLength etc, check documentation for complete listing) and these return a valid value or a null if not found. This is more performant then the earlier APIs when it comes to error conditions. Anyway, that is a separate topic. So back to the code behind file. The modified method will look like the following

        private void AnimatorClick(object sender, RoutedEventArgs e)
        {
            Storyboard board = (Storyboard)TryFindResource("TestAnimation");
            if (board != null)
                board.Begin(this);
        }


Not only does this help reduce the code clutter in the code behind file, this will also allow designers and developers to work in parallel. It is the designer who can plan the required animation and put that in XAML and all the developer needs to bother about is its name to invoke in the code behind. The same holds true for any other resource that you want to include in the XAML and use the code behind.

BTW, I can do with even less code as below, but note that it doesn't allows for error handling and assumes that the resource will be present. This can become troubling during development when the animation logic may not yet have been added to the XAML and hence during execution it will fail. I will recommend using the TryFindResource method.

((Storyboard)this.Resources["TestAnimation"]).Begin(this);

March 26, 2007

Adding Event handlers for controls in WPF (XAML) applications

I have been extremely used to the way event handlers are added to the code behind files, be it web application or winform application, when working with Visual Studio. This could be done either by double clicking the form/control whose event you want to handle or go the event listing in the properties windows, pick the event and double click there.

However the same doesn't works for WPF applications. It doesn't work using the currently available WPF extensions that work with VS2005 or with March CTP of Orcas.

This missing support seems like a big handicap and is like going backwards. Writing the correct event handler signature is important to get the event to work correctly and this becomes a challenge. One can look up the documentation, but that incurs a hit on productivity. So what's the way out.

I recently hit upon a simple technique by which we can get the right event handlers added in no time and I used another feature of VS for it.

Assuming you have already created a new Windows WPF application and added controls to the XAML file and now want to handle events for the controls. Take for example you have an Image control, and you want to handle the mouse left button down event for this image control. First add the necessary attribute in the XAML for the requried event. VS intellisense comes handy for this. The XAML statement will look something like the following

<Image Name="imgCtrl" Source="/Images/map.png" MouseLeftButtonDown="MouseLBtnClickHandler"></Image>

Where MouseLBtnClickHandler is name you want to use for method in the code behind file. Next go to the code behind file and in the already added public constructor for the Window, just below the InitializeComponent() method, add code to create a new Image control. Next, using Intellisense or otherwise, start writing code to add new event handler using the += (C# syntax) for the event you want to handle. VS will at this time, popup a tooltip that will help you add a new method to handle this event, with the appropriate signature. See the figure below.

EventHandler.jpg

Go ahead and allow VS to add this code snippet for you by hitting the TAB key twice. New method will be added with the appropriate signature. Rename the method to the same name as mentioned in the XAML file and also delete the lines added in the constructor (newing up the control and adding the event handler). Compile and run the code and you will see the event handler correctly wires up for the respective event. The final code will look something like the following

public Window1()
{
    InitializeComponent();
}

void MouseLBtnClickHandler(object sender, MouseButtonEventArgs e)
{
     //your mouse left button down handling code goes here
}

[Edited: 13 Nov 2007] After adding a control in the XAML, if you build the project once, the name for that control is visible in intellisence in the code behind. So you can do that while adding your event handlers. It will avoid you to create a dummy control just to add the event handler.

Comments welcome !

March 24, 2007

Using User Control in Windows WPF (XAML) Application

User controls are an essential part of writing Windows/Web applications. The other day I was trying to get a WPF user control (XAML) added to my WPF Window and was running into issues.

I am working on RTM Windows Vista Ultimate with VS2005 SP1 (with patch for Vista), .net fwk 3.0 RTM and November 2006 CTP of WPF extensions for VS. The scenario is as below.

I created a new WPF based Windows application and in the project also added a WPF User Control. I then tried to use this user control in the main application window. For doing this, one needs to first add the required namespace directive as below, to the root Window tag.

xmlns:my="clr-namspace:<NAMESPACE>"

The namespace qualifier can be anything that you want to use and I have used "my" here. This is then prefixed while using the user control. In the main XAML there will be statement like the following

<my:UserControl1 ....></my:UserControl1>

Unfortunately,  when you do this, the VS designer goes for a toss and doesn't renders the UI anymore. There is some issue in correctly identifying and working with the current assembly. The solution, however will build and run fine. Just that you loose the designer support.

I tried by moving the user control to a different project, adding reference to that project and then adding the assembly name the namespace tag, but that also didn't work. Though not a serious limitation, since the code does runs fine, but it will definitely hamper the page design since you can no longer view it.

I decided to give this a shot with the Orcas March 2007 CTP. Though there are a few issues in working with XAML, like automatic insertion of quotes for property values, automatic insertion of closing tag, when the opening tag is closed, doesn't work, but the user control issue is definitely resolved and the designer works properly. Adding the requisite namespace is also simpler due to intellisense support as shown in the figure below. userControlXAML.jpg

After this you can go ahead and add the necessary user control directive as something like below and all is well.

<my:UserControl1 Height="100" Width="100"></my:UserControl1>

Incidently, as soon as you type <my: intellisense will show the various controls available in this namespace for use and you will see UserControl1 also listed there.

BTW, the feature of not adding the closing tag automatically is actually good, since in earlier versions, if you are trying to add a container control tag, you need to yourself cut and the closing tag and paste where you need it. However with Orcas, you can add the opening tag, and then scroll down to where you want to insert the closing tag and type </ and intellisense will show the right options for closing tags.

March 15, 2007

BizTalk 2006 Handbook and other books

We recently launched the BizTalk Server 2006 Handbook that covers the key new features in BizTalk and our viewpoints around these features. Other books on VSTS and Features on .NET 2.0 are also published by my colleagues. You can find these at

http://www.infosys.com/technology/books.asp
http://www.infosys.com/microsoft/resource-center/technology-showcase/default.asp

 

March 13, 2007

"Access Denied" error whuile launching a Softgrid virtualized application on Vista

I am trying to launch an application on Windows Vista which was virtualized previously for Windows XP. However when I launch the deployed shortcut , Softgrid throws following error -

The Softgrid Client could not launch <Application Name>. Access is Denied. Error Code: 410038-0060922C-80070005

Has anyone experienced this error before?

Error while launching the shortcut 

The events logged on in the SFT Log List are as follows:
SFT Log List Text:
[03/12/2007 15:32:54.862 SWAP INF] {hap=105:app=IrfanView 3.9.8.0:tid=E2C:usr=sgtestadmin}
Elapsed time for upload: 0.031 seconds

[03/12/2007 15:32:54.877 ???? ERR] {tid=E2C:usr=sgtestadmin}
Unable to CreateProcess (rc 0060922C-80070005)
[03/12/2007 15:32:54.877 SWAP ERR] {hap=105:app=IrfanView 3.9.8.0:tid=E2C:usr=sgtestadmin}
The client could not launch Q:\Irfan-View_Irfan-Skilijan_3.99_MNT_1.0\i_view32.exe (rc 0060922C-80070005, last error 0).
[03/12/2007 15:32:56.593 TRAY ERR] {tid=EDC:usr=sgtestadmin}
The SoftGrid Client could not launch IrfanView 3.9.8.0.
Access is denied.
Error code: 410038-0060922C-80070005

ZTI of Vista over WAN

We successfully tested Zero Touch Installation of Microsoft Vista on a desktop having Windows XP SP2 installed using SMS OSD Feature pack and BDD over a WAN connection. The lab setup to test this consisted of following components:

 

Lab setup at WAN site# 1:
Box 1: Windows Server 2003 having SMS 2003 with OSD feature pack and BDD RC1 installed and configured                   

Box2: Windows Server 2003 on which we had:
Active Directory with a test domain created

DHCP Server with two scopes created for WAN site# 1 and 2.
DNS Server

Lab setup at WAN site# 2:
Target machines running XP SP2. These machines had SMS advanced client installed on them.
Network Setup:

  1. Create a separate VLAN for both WAN sites.
  2. Create a test domain. Ensure that the target machines are on the test domain.
  3. Create 2 scopes for WAN site 1 and 2 on the DHCP server.
  4. IP helper statement to be set on WAN site# 2 router. This is to ensure that the target machines get DHCP IP address from WAN site# 1 DHCP Server.
  5. Access Control Lists to be applied on the routers of both the WAN sites to access each other. Ensure that other network access is denied. Ensure to give permit UDP ACLs for bootps and bootpc
After the network set up was up and running, we created an image package with a 1.8 GB Vista image and included all 5 phases of BDD in the program. These programs would validate the target machine and also do a state capture and restore using USMT. Finally we created an advertisement scheduled to deploy this image package to the target machines over the WAN between site 1 and 2.
Result: Both the machines got re-imaged to Vista and all the data present was restored. After checking the logs we found out that the entire process (all the 5 phases of BBD) took about 50 minutes. We tested this again few more times and found that the average time was about 40-50 mins for install of a 1.8GB vista image over a shared WAN connection.

BizTalk Business Rules Composer's Namespace issue

Recently on a project support we faced an issue in using the BizTalk Rules Engine. It so happened that the code was getting generated via some XSD files that were themselves based on some legacy code, which we had no control on.

This code generated, thus contained classes with similar names in different namespaces. The project configuration requirements, forced all these to be in a single assembly and when this assembly was loaded in Business Rules Composer application, it failed to recognize the different namespaces.

To explain further, take the following example (the code below doesn't do anything and is only for demostrating the issue)

namespace BRETest
{
    public class MyClass
    {
        public int MyMethod(string x)
        {
            return 0;
        }
    }
}

namespace BRETest.AnotherNamespace
{
    public class MyClass
    {
        public int MyMethod(string x)
        {
            return 0;
        }
    }

    public class TestClass
    {
        public int AnotherMethod(string s)
        {
            return 56;
        }
    }
}

namespace BRETest.YetAnotherNamespace
{
    public class MyClass
    {
        public int MyMethod(string x)
        {
            return 0;
        }
    }
}

When this code is compiled and deployed in GAC and via BRE Composer, I try to create a new Vocabulary of type .NET Class or Class member, and select the above created assembly, I can see MyClass listed three times in the Select Bindings dialog, but in the details in the lower part of this dialog, I see the namespaces as same for all three. The BRE Composer isn't able to distinguish the different namespaces.

Now, I won't call the above a very good design but we had some limitations due to which we weren't able to alter the code. A workaround would have been segregate the namespaces into different assemblies, but there were quite a few such classes and splitting all across assemblies also wasn't really a feasible option.

We raised this with Microsoft and they confirmed this to be a bug and provided us with the hot fix. Things are working fine post the hot fix. I will publish the link for the KB article on this blog once the KB is officially released by MS. 

March 9, 2007

DST Impact on BizTalk Server

With the change in Daylight Saving Time as mandated by the Energy Policy Act 2005, systems running on BizTalk Server 2004 and 2006 may be impacted. Microsoft has published hot fixes for the same. Do review these and apply as applicable.

BizTalk Server 2004 - http://support.microsoft.com/kb/931960
BizTalk Server 2006 - http://support.microsoft.com/kb/931961

March 1, 2007

IIS 7 hosted sites not accessible from remote machines

Recently while working on my Vista machine, I was was working on a ASP.NET Web site and I wanted to have a colleage of mine have a look. Like always, I mailed him the URL and waited for him to view it and get back. To my surprise, he reverted stating he can't view it.

The error he was getting was "Internet Explorer cannot display the webpage". This was surprising since I was able to view the site locally on the Vista machine without any issues. This meant that IIS was configured and running properly. 

I tried to figure out the reason for this strange behavior since the IIS and world wide web services were all running properly on the machine. Turns out, it isn't really strange after all. It is one of those things done to make your machine more secure. To get this working, you need alter the default Firewall settings.

Run the Windows Firewall Settings Wizard (firewall.cpl) and in the Exceptions tab, scroll down and enable "World Wide Web services (HTTP)" option, as shown in the figure below. You will now be able to access the site properly. There is Support KB also on this, which I later found out.

FirewallSetting.jpg

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter