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)
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.