Wednesday, June 25, 2008

Static vs Dynamic Resources

In WPF you can use either reference a resource statically or dynamically. Most documentation floating around was fairly vague on what each system gave except for there was a slight performance penalty of choosing to access a resource dynamically. One analogy is that Static is like compile time look up and Dynamic is like run time. Terrible analogy.

Using StaticResource will evaluate the resource once, the first time that access is made i.e. Not at compile time.

Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.

A DynamicResource will be evaluated every time the resource is required.

Provides a value for any XAML property attribute by deferring that value to be a reference to a defined resource. Lookup behavior for that resource is analogous to run-time lookup.

So when would either be used? Considering performing a resource lookup dynamically carries a higher cost, you would prefer to use StaticResource. However what benefits does dynamic look up bring? Basically if you want to perform Skinning or any other type of system that could change the resource after it has been loaded then you should use Dynamic resolution. Now if that is just not the case for your WPF application then just stick with StaticResources. However I think that might be a wee bit short sighted.

As a guideline I believe that anything in the immediate context can be referenced statically. This basically includes any resources defined in the same XAML file that references them. If the resource is defined externally to the XAML file then Dynamically reference it.

   1:  <Window.Resources>
   2:    <local:EnumValueToDescriptionConverter x:Key="enumValueConverter"/>
   3:  </Window.Resources>
   4:  <ListView 
   5:       ItemsSource="{Binding Path=Users}"
   6:       ItemContainerStyleSelector="{DynamicResource myStyleSelector}" >
   7:    <ListView.View>
   8:      <GridView>
   9:        <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" />
  10:        <GridViewColumn Header="UserName" DisplayMemberBinding="{Binding Path=UserName}" />
  11:        <GridViewColumn Header="Status" DisplayMemberBinding="{Binding Path=Status, Converter={StaticResource enumValueConverter}}" />
  12:      </GridView>
  13:    </ListView.View>
  14:  </ListView>

Here we define an Enum Converter on line 2 and reference it statically on line 11. The style reference in line 6 refers to a style external to the XAML file so I reference it dynamically.

Monday, June 23, 2008

Move to Apple hardware

Time for a new laptop was on me and I have been weighing up on which piece of hardware to get. Basically I was considering another Sony Vaio, a Dell, possibly an ASUS and a Mac.

I pretty much discounted Sony as I was not happy with my last purchase which was a Sony. It is hard to put my finger on it but the whole experience was not quite right. It was light, fairly quick had quite a nice screen, but it had quirks. Cut/copy paste never worked properly?!? It –always- took two pastes for anything to actually paste. Often using drag to move or copy something crashed explorer quite often. Start up and shut down was getting pretty slow. On the flip side, when all was running it was fine for developing in VS and SQL, and, general performance for building and running apps was good.

I used to have an ASUS and was always happy with it except for its weight and battery life. To be fair this was mainly because it was a desktop replacement. I did pick up the ASUS laptop for a very good price when I did get it but the brand does not appear to be as popular here in Australia.

Dell just bothers me that it is all online. I know I am in the IT space and even spent many years in the e-commerce space, but I want to touch it, look at it and evaluate it.

15inMacBookPro Which leads me to Apple. The big reason with considering the apple is the feedback I have had. A number of people (that I work with and just read their blogs) have made the shift. Assuming you are and MSDN subscriber, you basically get two platforms for free. You get the confidence of high quality hardware. You also get all those treats that just come with OSX (Gargeband!). The real choice I was left with was which mac to get; MacBook or MacBook Pro? In the end I decided I wanted the slightly higher spec hardware from the MacBook Pro but found it very difficult to justify the large jumps in price for the extras on the higher spec’ed machines ($700 to get0.1 Ghz cpu increase and 215Mb more VRam). I ended up getting the Basic MacBookPro with an upgrade to 4GB of ram. Initial tests on Vista Ultimate running on Bootcamp have a performance index of 5.0 which thumps my old Sony score of 3.4.

Thursday, June 12, 2008

CurrentCulture vs CurrentUICulture

I have been guilty of using the CurrentUICulture where I shouldn’t. I made the assumption that the CurrentUICulture would be the thing I want to use to do things on my UI like formating and displaying a date. *WRONG*!

After one of the guys at work asked me why his FxCop told him off for not passing a IFormatProvider into his string.Format(..) I told him to just pass in CultureInfo.CurrentUICulture. Well I was wrong. We are in Australia and it started formatting his dates as mm/dd/yyyy not dd/mm/yyyy. A quick Google showed me the error of my ways. Basically always just use CultureInfo.CurrentCulture. The CultureInfo.CurrentUICulture is actually used by ResourceManager to identify which resource dictionary to use to show text to the user. Now this is great for Globalization but not to be used for localization. Gee don’t they sound like the same thing….?

WPF updates on Database changes

When using WPF in a smart client environment it always seemed natural that with a local datastore I should be able to listen to data changed events from the database. I have bundled a couple of systems together in a spike* to show that it is possible. Note the style implemented here is only useful where the database has one user (ie a smartclient application).

*spike is my way of excusing awful code.


I have taken the databinding goodness from WPF that automatically updates thanks to INotifyPropertyChanged. I have thrown a little visual clue in to show the data that has been modified. The row that was updated glows yellow.

Next I use a dictionary of WeakReferences in my repository to only hand out pointers to “Customers” in the dictionary. As they are weak references its not a big overhead to store them.

Next I use the service broker technology available from SQL 2005 up. The great thing here is that it is available on SQL Express which is perfect for Smart Client applications. Basically I add a trigger to each table (only customer at the moment) and add all the modifications to a queue as XML data.

Last I have a class that listens to the database called  RepositoryNotification. It basically runs in the background thread and using the Service broker queue technology it waits for triggers to place XML on the queue and then returns it as data. This all works great. At the moment the code that translates the xml is just awful so my apologies up front.

Note this quick spike currently only supports one row updates at a time (due to my crappy XML de-serialization) and doesn't support inserts or deletes. Inserts and deletes could possibly require some “business logic” to identify if the new row should be shown or the deleted row to be removed.


Adam Machanic has a brilliant tutorial on Service broker for those interested. Most of my SQL code was ripped from these tutorials. I think it was supposed to be a 3 part series but I can only find part 1 and part 2.

Thursday, June 5, 2008

CAB Module Configuration

One of the issues we face when developing a composite application is where module specific configuration belongs. There seems to be three approaches to the problem.

  1. Put it all in the shell’s app.config. If this is the answer one may want to question why the application is a composite one.
  2. Have a build task that merges module config into the app.config
  3. Have each module just deal with its configuration in isolation.

Option three is my personal preference as I think this lowers the requirements on possibly already complicated build/deploy routines and gives a level of isolation I associate with a composite application. If we were on the web platform we could just create new application domains for sub domains or sub-directories. How can we give similar isolation for client applications?

The .Net framework give us the ability to get config setting very easily from the executing assembly’s config using good old System.Configuration.ConfigurationManager. (still annoys me that System.Configuration is a seperate assembly to reference).

However using the  ConfigurationManager in the default manner is of no use in the composite application world. We have to look to some of its other features to get what we need.  ConfigurationManager provides a (somewhat misleading) method named OpenMappedExeConfiguration.  It actually allows access to non executable assemblies ie a dll. In this example we use the standard of a “.config” suffix to an assembly name to identify the module config.

    ExeConfigurationFileMap map = new ExeConfigurationFileMap();
    map.ExeConfigFilename = this.GetType().Assembly.Location + ".config";
    if (File.Exists(map.ExeConfigFilename))
        _configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

Now our _configuration variable can be used in a similar fashion to ConfigurationManager. We have access to our old favorite properties AppSettings and ConnectionStrings. We also can get config sections by using the GetSection method.

Hope this little insight helps building your composite applications in a little bit more isolation.

*Thanks to Grae for the base code.