DCSIMG
December 2009 - Posts - Technicals and Technicalities

Technicals and Technicalities

Ariel's uneditable Bliki

December 2009 - Posts

DataTemplates for ViewModels Resource Location

Hey folks.

I have an extensible system, where an addin can add a new UI component in the form of a ViewModel object, and a corresponding DataTemplate.

My app needs a way to load all of those DataTemplates as resources before the ViewModel is “shown” – so a dynamic resource location is required.

At some “UI initialization” point I have this piece of code:

var resourceUris = _Services.OptionPacksProvider.AllPacks.SelectMany(
    x => x.ResourceUriForDataTemplates).Distinct();
foreach (Uri resourceUri in resourceUris)
{
    _View.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = resourceUri });
}

And every option pack is responsible to return the URI. It does that using a nice little method, which works based on the convention that for a viewmodel class called “Project.Namespace.XXXViewModel” – there’s a resource dictionary file adjacent to it (in the same project folder) called “XXXView.xaml”. It’s a good convention regardless.

Using the following method you get the pack URI for the resource dictionary:

public static Uri Locate<TViewModel>() where TViewModel : ViewModelBase
{
    var viewmodelType = typeof(TViewModel);
    string shortAssemblyName = viewmodelType.Assembly.GetName().Name;
    string trimmedNamespace = viewmodelType.Namespace.Substring(shortAssemblyName.Length);
    string locationBasedOnNamespace = trimmedNamespace.Replace(".", @"/");
    var viewModelName = viewmodelType.Name.TrimX("Model");
    return new Uri(string.Format(@"pack://application:,,,/{0};component{1}/{2}.xaml", 
        shortAssemblyName, locationBasedOnNamespace, viewModelName));
}

(Caveats: the project name should equal the assembly name, and the default namespace should equal the project name)

Contextual Extension Methods

Me like!

 

int sleepTime = 1.Seconds();
while (condition)
{
    Thread.Sleep(sleepTime*=2); 
    if(sleepTime>10.Minutes())
    {
        //give up
        return;
    }
}
DoWork();

 

And no, those extensions are not defined under the System namespace.