Jun 26, 2012 at 12:21 PM
Edited Jun 26, 2012 at 2:11 PM
|
For designtime support I derive from a ViewModel class and add desgintime data in this class. The naming convention is that the derived designtime class has the suffix *Design. And use that class for d:DataContext (with d:IsDesgintimeCreatable=true). So
for example for MyViewModel I would have a derived type MyViewModelDesign that I then use like this:
d:DataContext="{d:DesignInstance pre:MyViewModelDesign, IsDesignTimeCreatable=True}" Caliburn:Bind.AtDesignTime="True"
Unfortunately the ViewLocator will not be able to locate the Views for these designtime types, since there is no rule for this.
So my namingconvention is that "ViewModelDesign$" should be replaced with "View" to locate a view. This should be done only at designtime.
How can I achieve the desired effect? I suppose I need to use ViewLocator.AddTypeMapping?
But what are the correct parameters?
From a pure regular expression perspective this works:
[Test]
[TestCase("My.Name.Space.MyViewModelDesign", Result = "My.Name.Space.MyView")]
[TestCase("My.Name.MyViewModelDesign.Space.MyViewModelDesign", Result = "My.Name.MyViewModelDesign.Space.MyView")]
[TestCase("My.Name.Space.MyViewModelDesignX", Result = "My.Name.Space.MyViewModelDesignX")]
[TestCase("MyViewModelDesign", Result = "MyView")]
[TestCase("MyViewModelDesignX", Result = "MyViewModelDesignX")]
public string RegexTest(string input)
{
const string pattern = @"(?<nsbefore>([A-Za-z_]\w*\.)*)ViewModelDesign$";
return Regex.Replace(input, pattern, @"View");
}
But when I do
const string pattern = @"(?<nsbefore>([A-Za-z_]\w*\.)*)ViewModelDesign$";
ViewLocator.AddTypeMapping(pattern, null, "View");
It still says it cannot resolve the views for my viewmodels.
|
|
Jun 27, 2012 at 7:01 AM
Edited Jun 27, 2012 at 9:39 AM
|
Turns out to be pretty easy:
/// <summary>
/// Called by the bootstrapper's constructor at design time to start the framework.
/// </summary>
protected override void StartDesignTime()
{
base.StartDesignTime();
ViewLocator.NameTransformer.AddRule("ViewModelDesign$", "View");
}
|
|
Developer
Jun 27, 2012 at 9:43 PM
Edited Jun 27, 2012 at 10:21 PM
|
Glad you figured it out. :)
But to ensure robustness of your mappings, you should do it like this:
var config = new TypeMappingConfiguration()
{
ViewModelSuffix = "MyViewModelDesign",
NameFormat = "{1}{0}",
ViewSuffixList = new List<string>(new[] { "MyViewDesign"}),
IncludeViewSuffixInViewModelNames = false
};
ViewLocator.ConfigureTypeMappings(config);
ViewModelLocator.ConfigureTypeMappings(config);
//test it
typename = "Test.ViewModels.MyViewModelDesignCustomer";
result = String.Join(", ", ViewLocator.TransformName(typename, null).ToArray());
//Output: Test.Views.MyViewDesignCustomer, Test.ViewModels.MyViewDesignCustomer
A key override of the configuration for your convention is the "NameFormat" property. Whereas, the out-of-the-box convention is "<entityname><ViewModel suffix>" (e.g. CustomerViewModel), yours is backwards--"<ViewModel
prefix><entityname>" (e.g. ViewModelCustomer or MyViewModelDesignCustomer).
If you need to override the automatic mappings for subnamespaces for your convention (i.e. *.MyViewDesigns.* -> *.MyViewModelDesigns.* and *.MyViewModelDesigns.* -> *.MyViewsDesigns.* instead of the default *.Views.* -> *.ViewModels.*
and *.ViewModels.* -> *.Views.*), then you need to do so by changing the DefaultSubNamespaceForViews and DefaultSubNamespaceForViewModels properties of TypeMappingConfiguration instance.
var config = new TypeMappingConfiguration()
{
DefaultSubNamespaceForViews = "MyViewDesigns",
DefaultSubNamespaceForViewModels = "MyViewModelDesigns",
ViewModelSuffix = "MyViewModelDesign",
NameFormat = "{1}{0}",
ViewSuffixList = new List<string>(new[] { "MyViewDesign"}),
IncludeViewSuffixInViewModelNames = false
};
ViewLocator.ConfigureTypeMappings(config);
ViewModelLocator.ConfigureTypeMappings(config);
typename = "Test.MyViewModelDesigns.SubNS.MyViewModelDesignCustomer";
result = String.Join(", ", ViewLocator.TransformName(typename, null).ToArray());
//Output: Test.MyViewDesigns.SubNS.MyViewDesignCustomer, Test.MyViewModelDesigns.SubNS.MyViewDesignCustomer
|
|
Jul 31, 2012 at 10:10 AM
Edited Jul 31, 2012 at 10:12 AM
|
Thanks for the reply. I will try to use the TypeMappingConfiguration instead. But I think you got my initial question mixed up a little bit. At designtime the viewmodels classes that are to be used by the ViewLocator end with ViewModelDesign instead of (at
runtime) ViewModel. That is the only difference.
So I guess all I have to override is:
var config = new TypeMappingConfiguration()
{
ViewModelSuffix = "ViewModelDesign",
};
|
|