I understand that by default CM will look for ShellView in Views folder to use as ShellViewModel View but I want to use the MainWindow instead... can this be done and how?
问题:
回答1:
How it Works
CM uses a set of View/ViewModel Naming Conventions, generally speaking, if you have a ViewModel named FooViewModel
CM will attempt to locate a type with a similar name of FooView
or FooPage
.
What if you really want "MainWindow" and "ShellViewModel"?
If you just wanted to use an existing "MainWindow" with an existing 'root viewmodel' then consider subclassing Bootstrapper<TRootModel>
and override OnStartUp
. This is a prescribed method, but can seem daunting.
(I have not tested this code.)
protected override void OnStartup(object sender, StartupEventArgs e)
{
var rootModel = IoC.Get<TRootModel>();
var rootView = new MainWindow();
ViewModelBinder.Bind(rootModel, rootView, this);
rootView.Show();
}
The above method, of course, would only apply to the initial view for the root view model shown during start-up. Future attempts to display a view for ShellViewModel
may work, or they may result in errors, I am not certain.
Extending Conventions
There are a few ways to customize the convention itself. The most flexible and direct method is to intercept/hook Caliburn.Micro.ViewLocator.LocateForModelType
, this allows you to modify the behavior/strategy applied during view location.
private static void CustomViewLocatorStrategy()
{
// store original implementation so we can fall back to it as necessary
var originalLocatorStrategy = Caliburn.Micro.ViewLocator.LocateForModelType;
// intercept ViewLocator.LocateForModelType requests and apply custom mappings
Caliburn.Micro.ViewLocator.LocateForModelType = (modelType, displayLocation, context) =>
{
// implement your custom logic
if (modelType == typeof(ShellViewModel))
{
return new MainWindow();
}
// fall back on original locator
return originalLocatorStrategy(modelType, displayLocation, context);
};
}
The above can be called from inside a Bootstrapper<TRootModel>.Configure
override:
protected override void Configure()
{
CustomViewLocatorStrategy();
base.Configure();
}
This method is more likely to play well with CM (in terms of any view caching, namely.) However, it still breaks conventions, and it's still a fair amount of code.
Registering Additional Suffixes?
One thing I want to point out, but have not had a chance to play with, is ViewLocator.RegisterViewSuffix
implementation. I believe if you executed ViewLocator.RegisterViewSuffix(@"Window")
then you could rely on CM to map MainViewModel
to MainWindow
.
This would allow for more expressive suffixes (such as Window, Dialog, Form, or others you may want to use.) Personally I dislike the use of 'View' as a suffix, I believe it's too generic (after all, they are all Views.)
回答2:
Caliburn.Micro doesn't look for ShellView by default, this is how things work. Let's say you have a bootstrapper defined like this:
class MyBootsrtapper : Bootstrapper<MyViewModel> { }
Then CM (Caliburn.Micro) will look for a view named MyView. So yes you can use MainWindow instead as long as your view model name is MainWindowViewModel.
I have answered the other question you have asked and it seems you don't fully comprehend CM so i really really advise you to Start Here and you can always check the projects Documentation on codeplex because it contains all updated information and documentation.
Edit:
Caliburn.Micro uses a simple naming convention to locate Views for ViewModels. Essentially, it takes the FullName and removes “Model” from it. So, given MyApp.ViewModels.MyViewModel, it would look for MyApp.Views.MyView.
Taken from official documentation here.