Infosys Microsoft Alliance and Solutions blog

« May 2008 | Main | July 2008 »

June 25, 2008

Silverlight - Getting Tooltip to work for individual ListBox Items

 The other day for a project work that we were doing in Silverlight 2.0 Beta 2, I was trying to get a tooltip to display for each item in the ListBox control. Things seemed to work fine if the content to be displayed in the tooltip was pretty much static or not dependant on individual items. I mean, I had a need that the tooltip should display different text per item, essentially data bind to some value for each item.

Does this makes sense? I guess it does to me, but you may be wondering about what exactly am I trying to achieve? Let me explain that with sample code. Below is the trivialized version of the code I was working on. There is a list of employees, who I am displaying in a ListBox.

The C# code is

namespace MTCTrackerApp

{

    public partial class UserControl1 : UserControl

    {

        public UserControl1()

        {

            // Required to initialize variables

            InitializeComponent();

        }

    }

 

    public class Employees : List<Employee>

    {

        public Employees()

        {

            Add(new Employee { FirstName = "Atul", LastName = "Gupta", Designation = "PTA" });

            Add(new Employee { FirstName = "Chandan", LastName = "Gokhale", Designation = "PTA" });

            Add(new Employee { FirstName = "Raghu", LastName = "Vempati", Designation = "TS" });

        }

    }

 

    public class Employee

    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Designation { get; set; }

    }

}

and XAML is

<UserControl

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

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

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d"

   xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows"

    x:Class="MTCTrackerApp.UserControl1" xmlns:local="clr-namespace:MTCTrackerApp"

    Width="640" Height="480" >

    <UserControl.Resources>

        <local:Employees x:Key="emps" />

    </UserControl.Resources>

 

    <Grid x:Name="LayoutRoot" Background="White" >

        <ListBox Margin="120,59,0,84" Height="150" HorizontalAlignment="Left" ItemsSource="{Binding '',Source={StaticResource emps}}" VerticalAlignment="Stretch" Width="200">

            <ListBox.ItemContainerStyle>

                <Style TargetType="ListBoxItem">

                    <Setter Property="Background" Value="Gray" />

                </Style>

            </ListBox.ItemContainerStyle>

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <Grid Width="192" HorizontalAlignment="Stretch" Height="35" Background="Transparent" >

                        <controls:ToolTipService.ToolTip>

                            <ToolTip Content="Technical" />

                        </controls:ToolTipService.ToolTip>

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="*" />

                            <ColumnDefinition Width="*" />

                        </Grid.ColumnDefinitions>

                        <TextBlock Margin="2" Text="{Binding FirstName}" VerticalAlignment="Center" />

                        <TextBlock Margin="2" Grid.Column="1" Text="{Binding LastName}" VerticalAlignment="Center"/>

                    </Grid>

                </DataTemplate>

            </ListBox.ItemTemplate>

        </ListBox>

    </Grid>

</UserControl>

When you run this, the output looks something like the following picture. Don't worry about why selected the item container style and the data template for items and definitely not if they are best for this scenario. They are only to help show the issue I faced and how I solved it. The Grid in the data template is marked with background as Transparent to become hit test visible. 

constanttip.jpg 

As is seen in the picture, the tooltip displays just fine, but this is static content and it displays the same value for all items. Now, instead of this, If I want to display say the Desgination of each Employee in the tooltip, I will tend to use code like the following. I am only showing the modified data template (the rest of the code is the same).

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <Grid Width="192" HorizontalAlignment="Stretch" Height="35" Background="Transparent" >

                        <controls:ToolTipService.ToolTip>

                            <ToolTip Content="{Binding Designation}" />

                        </controls:ToolTipService.ToolTip>

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="*" />

                            <ColumnDefinition Width="*" />

                        </Grid.ColumnDefinitions>

                        <TextBlock Margin="2" Text="{Binding FirstName}" VerticalAlignment="Center" />

                        <TextBlock Margin="2" Grid.Column="1" Text="{Binding LastName}" VerticalAlignment="Center"/>

                    </Grid>

                </DataTemplate>

            </ListBox.ItemTemplate>

With this change, the tooltip now actually doesn't displays anything as is seen in the figure below. It clearly means that the data binding isn't working corrently. Maybe the tooltip is created only when I hover on an item and at that time, there is no way the value of Degination can be obtained since there will be no indiciation of which Employee's Designation to pick up. Like in WPF, I don't know if there is a way to debug data bindings in Silverlight (if you know, do write back)

blanktip.jpg

After playing around with the idea for a while and almost on the verge of abandoning the idea of having item specific tooltip, I hit upon the following solution. See the modified XAML and code behind below.

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <Grid Width="192" HorizontalAlignment="Stretch" Height="35" Background="Transparent" Loaded="Grid_Loaded">

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="*" />

                            <ColumnDefinition Width="*" />

                        </Grid.ColumnDefinitions>

                        <TextBlock Margin="2" Text="{Binding FirstName}" VerticalAlignment="Center" />

                        <TextBlock Margin="2" Grid.Column="1" Text="{Binding LastName}" VerticalAlignment="Center"/>

                        <TextBlock Visibility="Collapsed" x:Name="dummy" Text="{Binding Designation}" />

                    </Grid>

                </DataTemplate>

            </ListBox.ItemTemplate>

 And add the event handler logic in the code behind. 

        private void Grid_Loaded(object sender, RoutedEventArgs e)

        {

            Grid grid = sender as Grid;

            TextBlock txt = grid.FindName("dummy") as TextBlock;

            ToolTipService.SetToolTip(grid, txt.Text);

        }

dynamictip.jpg

As you would have understood by looking at the code, I am handling the creating of each ListBoxItem by the way of handling the Grid's loaded event. In that I am creating a Tooltip from code behind and using the dummy TextBlock (which isn't visible but present only to help get the required value to display), I specify the content for the Tooltip and attach it to the Grid and thus achieve data binding for Tooltip indirectly.

If you know of a different way to do this, do write back. BTW, Interestingly, when using Tooltip direclty in the XAML code, the XAML files fail to load in Expression Blend 2.5 June CTP.

June 24, 2008

Silverlight - missed compiler error

Recently during my attempts to program with Silverlight landed me with a runtime exception (System.Windows.Markup.XamlParseException) with error as AG_E_PARSER_BAD_PROPERTY_VALUE. Fortunately, the error also provided line and column number in XAML. However when I looked at the XAML, it looked well formed and there wasn't any compilation error as well.

It was then that i realized that the compiler had actually missed catching the fact that I had defined click event handler for a Button in XAML, but not written it in the code behind. Having worked with WPF, I know that such errors are caught at compile time. I am surprised why Silverlight compiler missed this.

 

June 23, 2008

Downloadable implementation plans for PerformancePoint server 2007

Whole set of documents and templates related to PPS implementation plan is available here. This should be very helpful for project teams which uses PPS.

June 12, 2008

Migrating Comparis Silverlight Challenge App to Silverlight 2.0 Beta 2

With the Silverlight 2.0 Beta 2 now available, I finally decided to take the plunge. So far, I had been focusing on WPF, but knowing that Silverlight is the next big wave for RIA development, I could not stay away longer.

A few fellow colleagues have been working with Silverlight 2.0 Beta 1 and I heard from them that Beta 2 has been a bit of a challenge considering the various breaking changes from Beta 1 to Beta 2. Fortunately these were mostly functional/API issues with Silverlight controls and not like the interesting issue faced by my colleague Kishore with his attempt to work with .net 3.5 SP1 beta. Since I was new, I started with the Comparis Silverlight Challenge Application and the HOL created by Swiss MSDN Team.

The lab proved to be pretty useful both in terms of quickly knowing the way around Silvelight, Expression (which wasn't much different from what I was used to doing in WPF) and also understanding the issues when moving from Beta 1 to Beta 2. Here I document the various things I did to get the lab working. If you want to follow along, you can download the Lab document and code from the site mentioned above and start on.

To get the existing application to compile and run as is, on my VS 2008 RTM, .NET framework 3.5 (not SP1 beta as yet) Silverlight 2.0 Beta 2 and Expression Blend 2.5 June Preview, I had to do the following.

1. When I opened the solution in VS 2008, It prompted me for upgrade, which I readly accepted and did.

2. Changed the ComparisSilverlightChallengeTestPage.html page to point to Silverlight version Beta 2. See bold faced content below

 <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">

3. Changed the ComparisSilverlightChallengeTestPage.aspx page by removing the Version="2.0" and replacing it with MinimumVersion="2.0.30523".

4. Next comes setting the database. Since I didn’t have SQL Express, I had to attach the ComparisCarfinder.mdf to my local SQL 2005 Instance. While attaching, it took the name of the database as the full file path ("C:\Silverlight-HOL\Silverlight Challenge Solution Kit CSharp\ComparisSilverlightChallenge_Web\App_Data\ComparisCarfinder.mdf"). I thus had to rename this to ComparisCarfinder. After this I added the BUILTIN\Administrators as dbowner to this database. This is not a good security setting, but to keep things simple for now, this is what I did.

Due to these changes, the DBML (LINQ To SQL file) had to undergo some changes since my data was no longer coming from the SQL Express edition. I had to modify the connection string that was currently being used. For this I right clicked and opened ComparisCarfinderDB.dbml with XML editor. The connection string is available right toward the top and I changed this from

<Connection Mode="ConnectionString" ConnectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\ComparisCarfinder.mdf;Integrated Security=True;User Instance=True" Provider="System.Data.SqlClient" />

to

<Connection Mode="WebSettings" ConnectionString="Data Source=.;Initial Catalog=ComparisCarfinder;Integrated Security=True" SettingsObjectName="System.Configuration.ConfigurationManager.ConnectionStrings" SettingsPropertyName="ComparisCarfinderConnectionString" Provider="System.Data.SqlClient" />

The ComparisCarfinderDB.designer.cs also had to be updated. The current

    public ComparisCarfinderDBDataContext() :

        base("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\ComparisCarfinder.mdf;"+

                        "Integrated Security=True;User Instance=True", mappingSource)

    {

        OnCreated();

    }

 was replaced with

    public ComparisCarfinderDBDataContext() :

        base(global::System.Configuration.ConfigurationManager.ConnectionStrings["ComparisCarfinderConnectionString"].ConnectionString, mappingSource)

    {

        OnCreated();

    }

In the Web.config file just before the <appSettings/> tag inside of <configuration> tag, add the following new section

    <connectionStrings>

      <add name="ComparisCarfinderConnectionString" connectionString="Data Source=.;Initial Catalog=ComparisCarfinder;Integrated Security=True"

            providerName="System.Data.SqlClient" />

    </connectionStrings>

Note that doing all these changes manually can be a bit difficult and prone to error. Another easier way is to remove the existing ComparisCarfinderDB.dbml and related files from the Solution and add a new LINQ To SQL file and give it the same name. However with only this, things will not work and you will most likely get a 404 runtime error. This happens since in the existing ComparisCarfinderDB.designer.cs file, the Tables are additionally also tagged as DataContracts which goes missing in the newly generated files. This causes run time exception since the service is no longer aware of how to serialize the data. You can in such a case, replace the newer designer.cs file with the older one, but don’t forget to reset the connection string part as shown above.


With these changes in place, I was able to successfully build and execute the application and see the site as shown on page 9 of the HOL. So far so good and now beguns the actual fun of working with Silverlight 2.0.

The HOL mentioned about a security warning that you might get when initially opening the solution in VS. I didn’t get one there, but while working with Step 1, when I tried to open Page.xaml in Expression Blend 2.5 June Preview, I did get the warning. Post this working with HOL was fairly simple, till I hit Step 7.

HOL Step 7
This step talks about using WatermarkTextBox control. With Silverlight 2.0 Beta 2, this control is no longer available. I can't understand why? Has anyone come across any explanation for why this happened? Anyway, I now had an option of using TextBox control or build a watermark type TextBox on my own. Since I am still learning Silverlight I didn't want to get into writing custom controls, do I reverted to regular TextBox control.

Post this I was faced with another issue. For some reason, Expression Blend didn’t show DataGrid in the asset library and I tried to add it from VS I would get a FOMATETC error. Forums are saving grace and I found a similar query here. Following the suggestion theer I removed and added all the System.* references again and things started to work.

Surprisingly, after adding the DataGrid, both Expression and VS became slow and for some time the changes in one would not even reflect in another. So I had to close both Expression and VS and reopen and continue.

HOL Step 8
While adding the code, I modified the code snippet 8c as below and the DataGrid didn’t crash. I assume that the issue has been fixed in Beta 2.

        // Async event handler: Web service call

        void client_GetExpandedAdsCompleted(object sender, GetExpandedAdsCompletedEventArgs e)

        {

            myAds = e.Result.ToList();

            DataGridCars.ItemsSource = myAds;

 

            if (e.Result.Count() == 0)

            {

                HtmlPage.Window.Alert("No cars matching your qurey where found.");

            }

        }

HOL Step 10
While setting the event handler for the ValueChanged event, I got an error that the method name is invalid. It took me a moment to realize the extra blank space before the “_” in the HOL document and coping and pasting hence was causing the error.

After adding all the code as in this step, I realized that the TextKilometers was changing correctly, but the ListBoxImages wasn’t showing the right set of images. Debugging helped me realize that the MouseLeftButtonUp event from Slider wasn’t firing. Interestingly, this seems to be the feature of Beta 2 slider. See here. There is a discussion about writing custom slider or extending the existing one, but since I wanted to keep things simple for now, I did a dirty little trick as below

        private void SliderKilometers_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

        {

            if (TextKilometers != null)

            {

                TextKilometers.Text = ((int)e.NewValue).ToString();

            }

         SliderKilometers_Click(sender, null);

        }

This got the ListBoxImages working, but needless to say that it killed the UI. Since the filtering of data is happening on the same thread, the slider becomes unresponsive till the time the filter from the data is done. Another option will be to run this in background thread. That I will try later, once I get everything else working.

HOL Step 11
The Event handler names again have extra spaces so I had to be careful when copying and pasting these names. I guess a better option will be to type names directly or type the event name in VS in XAML view and let VS propose the default name for the event handler.

I thought of further extending the functionality here by getting the selected items into view. So I modified the code as below 

 

        private void DataGridCars_SelectionChanged(object sender, EventArgs e)

        {

            ListBoxImages.SelectedItem = DataGridCars.SelectedItem;

         ListBoxImages.ScrollIntoView(ListBoxImages.SelectedItem);

        }

 

        private void ListBoxImages_SelectionChanged(object sender, EventArgs e)

        {

            DataGridCars.SelectedItem = ListBoxImages.SelectedItem;

         DataGridCars.ScrollIntoView(DataGridCars.SelectedItem, null);

        }

I have set the DataGridColumn to null since I don’t care which columns are displayed for now.
Interestingly the code for DataGrid works, but ListBox didn’t get the selected item into view. I tried setting the StackPanel in ListBox’s ItemPanel template to Vertical and the scroll into view functionality worked perfectly. So this seems to be an issue when the ListBox is set as horizontal. I guess the ListBox doesn’t realize that the content inside it is set horizontally. It may hence be better if ListBox itself supports a Orientation property rather than I having to change it by putting my own StackPanel.

HOL Step 12
When adding the ListBoxDetails control, I had to set the Height to Auto and VerticalAlignment to Stretch to get the required size of the control. I did a few further changes like, made the Rectangle a bit more opaque by using an Alpha value of 80%. So the Fill value was set to - #CCB7B7B7. In the animation, I reduced the Opacity of DataGridCars and ListBoxImages to 50%. So the final animation storyboard looked like

        <Storyboard x:Name="GridDetails_Animate">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">

                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/>

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="1"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/>

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="1"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="DataGridCars" Storyboard.TargetProperty="(UIElement.Opacity)">

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="0.5"/>

            </DoubleAnimationUsingKeyFrames>

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ListBoxImages" Storyboard.TargetProperty="(UIElement.Opacity)">

                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="0.5"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

And in the ButtonDetailsClose_Click event, I then reset the Opacity values back to 100% as below 

        private void ButtonDetailsClose_Click(object sender, RoutedEventArgs e)

        {

            GridDetails.Visibility = Visibility.Collapsed;

            DataGridCars.Opacity = 1;

            ListBoxImages.Opacity = 1;

        }

This worked fine, though for some reason, the opacity effect on DataGrid’s header row wasn’t that visible. The header row still appeared to be fully opaque.

HOL Step 14
The customization of DataGrid template as such was fine, but there is one difference that I had do. The namespace prefix System_Windows_Controls was used already when I had added DataPicker control and this pointed to clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Extended. The DataGrid isn’t in this namespace and hence I had to create my own namespace prefix as xmlns:ctrls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data". Hence when I modified the DataGrid to use custom template I had to replace System_Windows_Controls with ctrls everywhere. Post this change, things worked, but surprisingly, Expression started to give an error and would no longer load the designer. For the code where the column width is set as “<ctrls:DataGridTemplateColumn Width="150" Header="CarImage">”, I got the following error in Expression
“The TypeConverter for “DataGridLength” does not support converting from a string”
Saw a similar error posted on the forum here and I also went ahead and voted for the same here

HOL Step 15
Finally reached the end of the HOL and the last part of templating the Slider control also had some issues. The templating logic as such worked fine and I could see the modified Slider at run time, but it neither reacts to clicks nor is it initialized to the max value as before. The Width also though set to 200, doesn’t visually look correct (see figure below). Is this related to my not having set any visual states as per the new VSM feature in Beta 2? I need to experiment further. If you have any idea on this, do write back.

SliderTemplate.jpg

With this, the experimentation with Silverlight 2.0 Beta 2 and migrating the Camparis Carfinder application was over.

June 11, 2008

Why I Love Working with the Betas...

Software in Betas are generally funny to work with. You never know what would work and what would not, when your machine would crash, what existing applications would stop working. And add on top of everything – lack of documentation. Worse still – incorrect documentation.

Well, that’s all part of the game once you are entrusted with the job of exploration, an Amerigo Vespucci of technology, and you sneak into unknown territories, click on anonymous buttons, read through documents that cry to be spell-checked, crash your applications, reboot your machine and sleep with title-less dialog boxes circling your eyes.

Funny, ain’t it? And if you think that would be funny, then get a load of what happened this morning. So, we are one of those nice people of the noble Amerigo clan who set out with another expedition to explore the latest kid on the technology block – the .NET Framework 3.5 SP1 Beta1. And one of my colleages sent me a mail “I was trying to install .NET Framework 3.5 SP1 Beta1 and got this message :).”

 

Funny Error Message

 

And that, my friend, is just how every exploration begins. A funny behavior where the installation asks the installation itself to be closed to proceed with the installation. You figure. I love working with the Betas.

June 9, 2008

'Devigners' ?... or more complete software developers ?

Since the beginning of this year, I have seen some blogs, including posting by Heather Solomon, Shane Morris and Ryan Stewart where they all have referred to a new entity in software development world called ‘Devigner’.  Devigner sure sounds fancy; but in essence a Devigner = Developer + Designer!

Discussions about the advent of these ‘Devigners’ have  a lot to do with an  interesting article Shane Morris at Microsoft wrote some time back. The article talked about possible design talent shortages in case Rich Media Applications (RIA) take off after the arrival of new Microsoft Design technologies.


Design technologies coming out of Microsoft like WPF and Silverlight, and in particular the design tools like Expression Design and Expression Blend are certainly having an impact in this direction.  They are allowing developers to write RIAs leveraging the Microsoft technology stack. They are also streamlining the Designer- Developer workflow. But most importantly, these technologies are lowering the bar on the design skill needed to create cool-looking interactive effects.


This situation where more people want to build rich, interactive applications is bound to create a higher need for designers. It has a lot to do with the complexity that is inherently associated with the richness of these applications.  Something simple and straight forward can be built with minimal design intervention. For higher complexity and bigger visual impact, the need to involve someone with good design skills becomes more pressing.


Designers, due to their mindset (as well as their training) are lot more comfortable with complex problem spaces. They are trained to seek multiple solutions for one design problem. But most importantly they are also trained to addresses the functional, emotional and aesthetic needs through one holistic design. For developers, the aesthetic sensibilities and ‘artistic’ skills necessary to conceive cool UI design solution always seem like an impossible hurdle to cross.


Given that good design talent is hard to find, and things may get worse with advent of above mentioned technologies, what is the way forward? Do we need those “Devigners”, people who are comfortable in performing either role with equal ease?  Or can we train an average developer on certain core interaction design skills and expect things them to deliver well?


My observation is that for a large number of software projects, the second option is not as bad as it may look. Let’s first consider the advancements in modern day design tools. These tools, including Expression Design and Expression Blend, are rich in features that allow a novice user to explore and crate engaging interactions with minimal experimentation. Their interfaces are relatively easy to learn and a lot of complex activities can be automated. There are ways to incorporate or reuse design elements like styles thereby making it easy to isolate the high-end visual design inputs into tangible code files – something a lot of developers reverse engineer to understand the ‘design’. But just good support from tools and technologies is not enough. What about core design skills that ensure a creative and holistic solution?


I have seen that with some rigorous training and hands-on practicum, a software developer with interest in user interface design can be effectively used to fill the void of ‘that unavailable UI design resource’. This is particularly true for line-of-business applications where a certain level of adherence to well accepted interface design standards is expected.


In my view, the four areas where a software developer needs training are:
a.       Creative design process and core interaction design theories
b.      Basic visual design and layout development principles
c.       User interface design patterns
d.      Basic usability engineering principles and practices


While, this approach solves the immediate project staffing needs and ensures adherence to minimum design standards; it actually has much bigger rewards in the long term.
Exposure to creative design process makes the developer far more comfortable to open-ended problems - or problems with emerging uncertainties. It equips them with some lateral thinking techniques. And the biggest plus is that they learn to focus their efforts on satisfying the end-user through all their actions. This way, they may not turn into ‘Devigners’, but they sure do become ‘more complete’ developers. In this ‘SOA ‘and ‘Mash-ups’ driven era, where much more data is available for manipulation and display, good UI skills in my view are a ‘must have’, not ‘good to have’ to be categorized as a good developer.


In the weeks to come, I will address these training areas separately in follow-up blogs.

Silverlight 2.0 Beta 2

If you have been following Silverlight, you would already be aware that Microsoft released Beta 2 of Silverlight 2.0 last weekend. Check out more details on Scott's blog. The release also includes release of updated extension for VS 2008, Expression Blend 2.5 June Preview and DeepZoom composer. Also check out here for feature listing.

However moving from Beta 1 to 2 may not be a smooth sailing as there are many breaking changes. Read about them here. The list has been further updated and available here.

WPF - Bound property updates before Target property

Recently while answering a query on WPF forum, I found an interesting behavior. In case you have two way binding set on a property, the property to which you bind too, updates before the property to which the bound value is assigned. Check out discussion and a sample on this here.

This seems to similar to another behavior with ComboBox that i had described here.

June 5, 2008

WPF ComboBox SelectionChangedEvent

 When programming with the Combobox and handling its SelectionChangedEvent, you need to be a bit careful. The general expectation will be that when this event fires, the various properties like SelectionBoxItem or Text will give the new value, but that isn't the case.

The SelectedIndex does points to the newly selected item index, but the values of properties like SelectionBoxItem or Text still point to the old values and the new one selection hasn't really been updated. It is only after the event handler code that you write has completed execution that these properties update.

Take a simple sample XAML as below

<Window x:Class="TestWPFApp.ComboTest"

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

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

   xmlns:local="clr-namespace:TestWPFApp"

   Title="ComboTest" Height="300" Width="300">

    <Window.Resources>

        <ObjectDataProvider x:Key="colorCol" ObjectType="{x:Type local:MyColorCollection}"/>

        <local:MyColorCollection x:Key="colors" />

    </Window.Resources>

    <Grid>

        <ComboBox Name="cmbBox" SelectionChanged="cmbBox_SelectionChanged" Height="27" VerticalAlignment="Top" Margin="43,17,45,0">

            <ComboBoxItem>One</ComboBoxItem>

            <ComboBoxItem>Two</ComboBoxItem>

            <ComboBoxItem>Three</ComboBoxItem>

        </ComboBox>

        <Button Content="Click" Name="myBtn" Margin="93,101,91,130" />

    </Grid>

</Window>

We intend to disable the button when the value selected in ComboBox is "One" and keep it enabled otherwise. If you were to write code like the following, you will be in for a surprise since as i mentioned earlier, the value of SelectionBoxItem still points to earlier value while the SelectionChangedEvent is being processed. 

        private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            if (string.Equals(cmbBox.SelectionBoxItem.ToString(), "One"))

                myBtn.IsEnabled = false;

            else

                myBtn.IsEnabled = true;

        }

This is easily addressed by using the properties like SelectedIndex directly. So in our case, since we know the value of "One" is at index 0, we can use that directly as below

 

        private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            if (cmbBox.SelectedIndex == 0)

                myBtn.IsEnabled = false;

            else

                myBtn.IsEnabled = true;

        }

 However the if you want really work with the right values and not rely on prior knowledge of indices, you would want to work with the details available in the SelectionChangedEventArgs parameter that is available for this event. This object has additional properties like AddedItems and RemovedItems that will give the details of the item that is about to be selected and the item that is about to be deselected. These can contain multiple values since the same object is used in cases like multiselect ListBoxes or ListView controls. So a code like the following is what you can actually write to get the same effect and without relying on hardcoded index values.

        private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            myBtn.IsEnabled = true;

            foreach (ComboBoxItem item in e.AddedItems)

            {

                if (string.Equals(item.Content, "One"))

                {

                    myBtn.IsEnabled = false;

                    break;

                }

            }

        }

Finally, just to prove the point, I ran the application and put a debug breakpoint in the SelectionChangedEvent handler code. The figure below shows that while the debugger has hit the code, the ComboBox drop down hasn't still collapsed. The dropdown can still be seen over the VS window while i am debugging the event handler. It is only after I exit the handler, will this drop down disappear and the new selection appear in the ComboBox's display area (and the values of SelectionBoxItem and Text property get updated).

ComboBox.jpg

Feel free to try this yourself and verify.

The “framework” conundrum in ERP/CRM

What is the optimum limit to which we should customize an “off the shelf” product to meet the client’s need?

Microsoft Dynamics products have been positioned as more of a framework with “optimal” business processes built into the products rather than “hard-coding” all the business best practices that had been the selling pointy for most of the established ERP in the market. When Microsoft Dynamics brand was launched in market, the idea was to enable companies bring their processes into the system rather than following what is already provided by the product.

There are always people commenting on this positively or negatively, and both are right!

The ones in favor believe that any organization is like an individual with its own DNA and they need to work the way they have imbibed business principles and built their USP. It’s not that they would not have a P2P, O2C or Hire to Retire processes, but just that they would have their own way of achieving this in the organization. What Microsoft Dynamics gives is a framework with all components laid out on a drawing board, needing someone to connect the dots and color the same to form a big picture in line with what the organization would like to be. It works on the principal of accepting organizations (whether big or small) as mature entities who know their business, pain-points, solution needs and budgets they would like to spend on achieving that. With this school of thought, the clients are more “collaborative” in nature and would look forward to working with the partner and reach an “optimal” solution at the cost which justifies the same. They would not be attracted by the buzz words in the markets and the latest fads as pushed forward by the “gurus” in the trade. To them the business realities are of utmost importance and so is user acceptance to the new solution.

The other school of thought advocates, “best of breed” solutions – saying that the product companies have worked with Global league players and with domain consultants and all these learnings have been incorporated in the packages. The packages can enable business transformation and help clients realize value by adapting the processes that the application provides and these are “best of breed” processes. These are in line with what the industry players are doing and what the latest trends in businesses and operations are. With these packages the clients can actually reap value because there are lots of learnings which have been incorporated into the products. There is lesser risk in these implementations as the processes already built into the application would be applied as a template in the organization.

Well, both are right!

But then I have full right to have my opinion. Smile

I go with the first school of thought as I think to any corporate, it’s the people, who are working with them, are the real assets. While the prime directive of any business is to make profit, it’s the “people oriented” companies that have had success in the long run. And when we turn that thinking on the “technology led transformations”, I would actually extend the phrase and call it “technology led transformation for the benefit of people”. Ultimately whatever package we use, we need to ensure that people are going to use it on day to day basis and the under experience has to be such that they themselves find value in using the product. With attrition and movement of people, retraining people on complex packages with complex transaction scenarios is a big task needing lot of investment in terms of time and money; needless to say the loss of business in the intervening period.

The companies who are in business are very much doing their operations in a streamlined process, which may not be executed properly due to lack of tools that can enable this. Sometimes it actually makes sense to streamline the processes first and then go for an application that can tie these processes together into a single ERP/CRM system and this ERP/CRM system needs to have that flexibility to adopt the “best for business” processes for the organization. The customizations that are done to achieve this does affect the upgrade path, but then there are other questions around when to upgrade, why to upgrade and at what cost which need to be evaluated. Can we go with the option of making people change the way they do business to suit the application as we are concerned only about the future upgrade cost? Isn’t it more realistic to look at current needs as well – isn’t the business benefit required now? Long live - “technology led transformation for the benefit of people”.

June 4, 2008

Windows 7 - What is it?

Windows 7 is the next generation Windows operating system what Microsoft is working on and is expected to hit the market somewhere in 2010. This is probably something that all of us know. But what are the key features that Windows 7 will offer? That is a question to which there aren't many answers today.

With the advent of .net, Microsoft had also brought in a new era of beta bits, CTP bits and RC bits. In a way this helped the community keep a close watch on what's coming and plan ahead. Many would have already started implementing production ready applications even before the particular product would RTM. I had written about my thoughts on this trend here.

However there have been many instances when some of the important features, that the community gets used to by playing around with these early bits, aren't present in the RTM bits and that is a big damper on spirits. Sometimes it may also mean calling off or redoing some of your own application work that was relying on these "no longer present" features.

The stance that Microsoft seems to be taking with Windows 7 and its feature disclosure is reverse of the current trend. In the recent interview Steven Sinofsky, Senior Vice President, Windows and Windows Live Engineering discussed about this change in readiness to disclose upfront about upcoming Windows 7. It is interesting to read the interview and see how Steven kept deflecting questions on specific features of Windows 7 and repeatedly said that the right information will be shared with the right set of partners.  Similar information is also available on the Vista blog site. There is one feature however that was showcased during the D: All Things Digital Conference by Julie Larson-Green, Corporate Vice President, Windows Experience Program Management and that is the Multi-touch feature. This brings the Microsoft Surface capabilities to Windows 7.

Is this approach of not disclosing the details, good? Well I think, it is both good and bad. Knowing too much upfront spoils the surprise and wow element. Take for an example that you want to watch a movie and you hear a lot about it from friends and also watched a few trailors. When you go to watch the movie, it won't appear all that great since the expectations were set to so high already that it fails to meet it.

Another factor will be better safe than sorry. In past there have been instances of missing features in final RTM bits and community obviously doesn't likes it. This is like minimizing the attack surface and have lower security risk. Disclose less so there are less chances of not meeting the expectations.

On the flip side, in todays' fast changing world, organizations do want to keep a watch ahead and plan their upgrades/migrations etc accordingly. There are organizations that tend to skip one version of OS. So if they had adopted Win XP, they will mostly not adopt Vista and wait for Windows 7. But if they don't know what's coming in that, it becomes difficult to plan for that version.

There is still time though it seems that Microsoft is playing safe right now, things may change in future. Who knows that by end of 2008 or early 2009, we may start to get more publicaly available information on Windows 7. I, for one, am keeping my fingers crossed and waiting for that to happen !

June 2, 2008

Where have I been?

It has been a pretty hectic last month with lot of travel. I had been travelling to synch up with our teams working from other DCs and then a week long training at our Mysore campus (I just love it !) and finally topped it with a week long vacation.

With a school going kid, whether i like it or not, summer is the time to take time off and be in Delhi (fortunately it wasn't very hot this time, due to lot of unexpected rains). Well, I am back now and will try to get back with new blog entries.

Thanks for being patient

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter