尽管命名约定相同,为什么 Caliburn Micro 绑定了一些视图而不绑定其他视图?
Why is Caliburn Micro binding some views but not others despite same naming conventions?
我有 3 个视图模型:
- App.ViewModels.LoginViewModel
- App.ViewModels.NavigationViewModel
- App.ViewModels.AbcViewModel
和 3 次浏览:
- App.Views.LoginView
- App.Views.NavigationView
- App.Views.AbcView
在我的 AppBootstrapper 中,LoginView 是这样加载的:
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
var windowManager = IoC.Get<IWindowManager>();
var loginModel = IoC.Get<ILogin>("Login");
windowManager.ShowWindow(loginModel, "LoginView");
}
但是,returns 找不到该 ViewModel 的视图。 除非我将 LoginView 的命名空间 更改为 App.Views.Login.LoginView 并保持 VM 命名空间不变。然后它工作正常。
成功登录后,我使用相同的过程加载我的 NavigationViewModel。 (在将命名空间更改为 App.Views.Navigation.NavigationViewModel 以便它实际工作之后)
目前,这给我留下了以下视图命名空间:
- App.Views.Login.LoginView
- App.Views.Navigation.NavigationView
- App.Views.AbcView
NavigationViewModel 是一个导体,它有一个 ViewModel 列表和一个用于显示它们的视图上的 TabControl。
不幸的是,我必须手动将我的 AbcViewModel 绑定到视图,否则不会显示任何内容。例如:
AbcView abcv= new AbcView ();
AbcViewModel abcvm= IoC.Get<AbcViewModel>("Abc");
ViewModelBinder.Bind(abcvm, abc, null);
我希望所有事情都使用 Caliburn ViewModel 优先方法完成,这样我就不需要担心手动绑定视图的问题。我遵守了该结构,但它不起作用。我哪里错了?
基本上,有没有一种方法可以让 Caliburn 在我创建 ViewModel 时创建并绑定我的视图?
我是否需要以某种方式为我的每个模型调用 ViewLocator?如果是这样,这与我目前正在执行的手动绑定有何不同?
有谁知道视图模型第一个 Caliburn 项目的完整示例(整个项目),我可以偷看一下?
感谢任何帮助,提前致谢。
马特
您不需要自己绑定任何 Views/ViewModels,Caliburn.Micro
会处理它。您只需通过覆盖 Bootstrapper
class 中的 OnStartup
来告诉 Caliburn.Micro
您的起点 class(参见 tutorial)。
您还必须在 App.xaml
中为 ResourceDictionary
提供 Bootstrapper
class 并删除 Startup
:
<Application.Resources>
<!--Declare your bootstrapper class-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:YourBootstrapperClass x:Key="bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
您的 Bootstrapper
class 必须派生自 BootstrapperBase
并在构造函数中调用 Initialize()
。这应该足以 Caliburn.Micro
绑定 views/viewmodels.
另外,如果你想在你的项目中使用 Dependency Injection
,你可以设置一个 SimpleContainer
并注册你想要注入的类型。您可以在 Bootstrapper
:
中执行此操作
public class Bootstrapper : BootstrapperBase
{
// Container for your registered types.
private SimpleContainer _container = new SimpleContainer();
public Bootstrapper()
{
Initialize();
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
// Tells Caliburn.Micro where the starting point of your application is.
DisplayRootViewFor<ShellViewModel>();
}
protected override void Configure()
{
// Register types you want to inject.
_container.Singleton<IWindowManager, WindowManager>();
_container.Singleton<IEventAggregator, EventAggregator>();
base.Configure();
}
protected override object GetInstance(Type service, string key)
{
// This is called every time a dependency is requested.
// Caliburn.Micro checks if container contains dependency and if so, returns it.
var instance = _container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
// Get all registered classes...
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
}
之后你可以像这样通过构造函数注入依赖项:
public class ShellViewModel
{
public ShellViewModel(IEventAggregator eventAggregator)
{
// You can use eventAggregator here. It is already injected.
}
}
Caliburn.Micro
使用命名约定,以便它可以自动发现 Views/ViewModels。您应该将文件夹命名为:Views
和 ViewModels
,并且您的 classes 应该命名为 YourClassView
和 YourClassViewModel
。这样 Caliburn.Micro
就可以找到他们。因此,如果您像这样设置 OnStartup
:
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
那么您的视图模型必须位于 ViewModels/ShellViewModel
中,您的视图模型必须位于 Views/ShellView
中。
我有 3 个视图模型:
- App.ViewModels.LoginViewModel
- App.ViewModels.NavigationViewModel
- App.ViewModels.AbcViewModel
和 3 次浏览:
- App.Views.LoginView
- App.Views.NavigationView
- App.Views.AbcView
在我的 AppBootstrapper 中,LoginView 是这样加载的:
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
var windowManager = IoC.Get<IWindowManager>();
var loginModel = IoC.Get<ILogin>("Login");
windowManager.ShowWindow(loginModel, "LoginView");
}
但是,returns 找不到该 ViewModel 的视图。 除非我将 LoginView 的命名空间 更改为 App.Views.Login.LoginView 并保持 VM 命名空间不变。然后它工作正常。
成功登录后,我使用相同的过程加载我的 NavigationViewModel。 (在将命名空间更改为 App.Views.Navigation.NavigationViewModel 以便它实际工作之后)
目前,这给我留下了以下视图命名空间:
- App.Views.Login.LoginView
- App.Views.Navigation.NavigationView
- App.Views.AbcView
NavigationViewModel 是一个导体,它有一个 ViewModel 列表和一个用于显示它们的视图上的 TabControl。
不幸的是,我必须手动将我的 AbcViewModel 绑定到视图,否则不会显示任何内容。例如:
AbcView abcv= new AbcView ();
AbcViewModel abcvm= IoC.Get<AbcViewModel>("Abc");
ViewModelBinder.Bind(abcvm, abc, null);
我希望所有事情都使用 Caliburn ViewModel 优先方法完成,这样我就不需要担心手动绑定视图的问题。我遵守了该结构,但它不起作用。我哪里错了?
基本上,有没有一种方法可以让 Caliburn 在我创建 ViewModel 时创建并绑定我的视图? 我是否需要以某种方式为我的每个模型调用 ViewLocator?如果是这样,这与我目前正在执行的手动绑定有何不同?
有谁知道视图模型第一个 Caliburn 项目的完整示例(整个项目),我可以偷看一下?
感谢任何帮助,提前致谢。
马特
您不需要自己绑定任何 Views/ViewModels,Caliburn.Micro
会处理它。您只需通过覆盖 Bootstrapper
class 中的 OnStartup
来告诉 Caliburn.Micro
您的起点 class(参见 tutorial)。
您还必须在 App.xaml
中为 ResourceDictionary
提供 Bootstrapper
class 并删除 Startup
:
<Application.Resources>
<!--Declare your bootstrapper class-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:YourBootstrapperClass x:Key="bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
您的 Bootstrapper
class 必须派生自 BootstrapperBase
并在构造函数中调用 Initialize()
。这应该足以 Caliburn.Micro
绑定 views/viewmodels.
另外,如果你想在你的项目中使用 Dependency Injection
,你可以设置一个 SimpleContainer
并注册你想要注入的类型。您可以在 Bootstrapper
:
public class Bootstrapper : BootstrapperBase
{
// Container for your registered types.
private SimpleContainer _container = new SimpleContainer();
public Bootstrapper()
{
Initialize();
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
// Tells Caliburn.Micro where the starting point of your application is.
DisplayRootViewFor<ShellViewModel>();
}
protected override void Configure()
{
// Register types you want to inject.
_container.Singleton<IWindowManager, WindowManager>();
_container.Singleton<IEventAggregator, EventAggregator>();
base.Configure();
}
protected override object GetInstance(Type service, string key)
{
// This is called every time a dependency is requested.
// Caliburn.Micro checks if container contains dependency and if so, returns it.
var instance = _container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
// Get all registered classes...
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
}
之后你可以像这样通过构造函数注入依赖项:
public class ShellViewModel
{
public ShellViewModel(IEventAggregator eventAggregator)
{
// You can use eventAggregator here. It is already injected.
}
}
Caliburn.Micro
使用命名约定,以便它可以自动发现 Views/ViewModels。您应该将文件夹命名为:Views
和 ViewModels
,并且您的 classes 应该命名为 YourClassView
和 YourClassViewModel
。这样 Caliburn.Micro
就可以找到他们。因此,如果您像这样设置 OnStartup
:
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
那么您的视图模型必须位于 ViewModels/ShellViewModel
中,您的视图模型必须位于 Views/ShellView
中。