Caliburn Micro MVVM 多个活动项和 IoC 依赖注入
Caliburn Micro MVVM Multiple Active Items AND IoC Dependency Injection
我偶然发现了一个问题,在CM的官方文档中没有找到解决方案。
我们的应用程序看起来类似于此图片:
在搜索 Whosebug 时,我找到了使用 Conductor<object>.Collection.AllActive
class (more active screens / views in shell caliburn micro or another MVVM framework) 执行此类操作的解决方案。我遇到的最大问题 运行 是,我找不到使用工厂进行依赖注入的方法。 ShellViewModel
的构造函数目前看起来像这样。
public ShellViewModel(
Func<FooterViewModel> footerViewModelFactory,
Func<LoginViewModel> loginViewModelFactory)
{
this.ActivateItemAsync(loginViewModelFactory);
this.ActivateItemAsync(footerViewModelFactory);
}
显然这是行不通的,因为ContentControl不能显示工厂,需要一个Screen。但是我如何首先设法将对象绑定到 shell,同时仍然保持依赖注入的特性?否则,一个简单的解决方法就是为 ViewModel 创建一个新实例并传递所有参数,这在我看来非常肮脏。
我终于想通了。虽然我讨厌 Java 中的工厂模式,但它在 Caliburn Micro 中似乎是必要的并且很有意义。
无论如何,我创建了一个类似这样的工厂:
public class FooterFactory
{
// Add all the needed interfaces you get injected from the IoC container here.
private readonly IMyInterface myImplementation;
public FooterFactory(IMyInterface myImplementation, ...)
{
this.myImplementation = myImplementation;
}
//Creates the ViewModel. You can also pass some parameters here.
public FooterViewModel Create(...)
{
return new FooterViewModel (..., this.myImplementation);
}
}
将工厂添加到引导程序后,就可以像下面那样轻松添加了。不过,我最初的方法存在一些问题。因此,我稍微更改了我的代码。
public ShellViewModel(
FooterFactory footerFactory,
Func<LoginViewModel> loginViewModelFactory)
{
this.ActivateItemAsync(loginViewModelFactory);
this.FooterViewModel = footerFactory.Create(...);
}
我的 XAML 看起来像这样。
<Window x:Class="My.Client.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
WindowState="Maximized"
WindowStartupLocation="CenterScreen"
Title="Dummy" Icon="/Resources/favicon.ico">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="120" />
</Grid.RowDefinitions>
<ContentControl Name="ActiveItem" Grid.Row="0"/>
<ContentControl Name="FooterViewModel" Grid.Row="1" />
</Grid>
</Window>
注意:正如我所说,这是我使用的代码的简化版本。无论如何,它应该强调解决这个问题的方法。这种方法的好处是,您不需要 Conductor<>.Collection
和多个项目控件。因此,您无需打乱对象的顺序,例如,如果一个对象的加载时间比另一个对象长,或者您必须停用某些对象。 + 如果你想在屏幕上显示更多内容(例如页眉、菜单栏等),你可以在 XAML 中创建多个 ContentControl
。
我偶然发现了一个问题,在CM的官方文档中没有找到解决方案。 我们的应用程序看起来类似于此图片:
在搜索 Whosebug 时,我找到了使用 Conductor<object>.Collection.AllActive
class (more active screens / views in shell caliburn micro or another MVVM framework) 执行此类操作的解决方案。我遇到的最大问题 运行 是,我找不到使用工厂进行依赖注入的方法。 ShellViewModel
的构造函数目前看起来像这样。
public ShellViewModel(
Func<FooterViewModel> footerViewModelFactory,
Func<LoginViewModel> loginViewModelFactory)
{
this.ActivateItemAsync(loginViewModelFactory);
this.ActivateItemAsync(footerViewModelFactory);
}
显然这是行不通的,因为ContentControl不能显示工厂,需要一个Screen。但是我如何首先设法将对象绑定到 shell,同时仍然保持依赖注入的特性?否则,一个简单的解决方法就是为 ViewModel 创建一个新实例并传递所有参数,这在我看来非常肮脏。
我终于想通了。虽然我讨厌 Java 中的工厂模式,但它在 Caliburn Micro 中似乎是必要的并且很有意义。
无论如何,我创建了一个类似这样的工厂:
public class FooterFactory
{
// Add all the needed interfaces you get injected from the IoC container here.
private readonly IMyInterface myImplementation;
public FooterFactory(IMyInterface myImplementation, ...)
{
this.myImplementation = myImplementation;
}
//Creates the ViewModel. You can also pass some parameters here.
public FooterViewModel Create(...)
{
return new FooterViewModel (..., this.myImplementation);
}
}
将工厂添加到引导程序后,就可以像下面那样轻松添加了。不过,我最初的方法存在一些问题。因此,我稍微更改了我的代码。
public ShellViewModel(
FooterFactory footerFactory,
Func<LoginViewModel> loginViewModelFactory)
{
this.ActivateItemAsync(loginViewModelFactory);
this.FooterViewModel = footerFactory.Create(...);
}
我的 XAML 看起来像这样。
<Window x:Class="My.Client.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
WindowState="Maximized"
WindowStartupLocation="CenterScreen"
Title="Dummy" Icon="/Resources/favicon.ico">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="120" />
</Grid.RowDefinitions>
<ContentControl Name="ActiveItem" Grid.Row="0"/>
<ContentControl Name="FooterViewModel" Grid.Row="1" />
</Grid>
</Window>
注意:正如我所说,这是我使用的代码的简化版本。无论如何,它应该强调解决这个问题的方法。这种方法的好处是,您不需要 Conductor<>.Collection
和多个项目控件。因此,您无需打乱对象的顺序,例如,如果一个对象的加载时间比另一个对象长,或者您必须停用某些对象。 + 如果你想在屏幕上显示更多内容(例如页眉、菜单栏等),你可以在 XAML 中创建多个 ContentControl
。