ShellViewModel Caliburn.Micro中的ViewModels参考 [英] ViewModels references in ShellViewModel Caliburn.Micro
问题描述
在此线程中:有人能提供导体T.Collection.AllActive用法的任何简单工作示例吗?我已经回答了一部分,但仍然很困惑。
In this thread : Can anybody provide any simple working example of the Conductor<T>.Collection.AllActive usage? I've had part of an answer but I'm still a but confused.
我只是想将所有视图模型都引用到ShellViewModel中,以便能够打开/关闭ContentControls,而无需将所有视图模型都注入构造函数中。
I would simply like to reference all my view models into my ShellViewModel to be able to open/close ContentControls, but without injecting all of them in the constructor.
在答案中,建议在ShellViewModel的构造函数中注入一个接口。如果这样做,是否必须将所有ViewModel注入实现该接口的类中?
In the answer, it is suggested to inject an interface in the constructor of the ShellViewModel. If I do that, do I have to inject all my ViewModels in a class that implements that interface?
public MyViewModel(IMagicViewModelFactory factory)
{
FirstSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
SecondSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
ThirdSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
Items.Add(FirstSubViewModel);
Items.Add(SecondSubViewModel);
Items.Add(ThirdSubViewModel);
}
此外,我想避免通过IoC.Get<>获取我的视图模型实例,如果我没记错的话,我认为它违反了IoC的原则。
在另一些示例中,它们在需要时创建新的viewModel,但是在这种情况下使用IoC有什么意义,特别是当我需要将服务注入这些新的ViewModels中时?
Also, I would like to avoid going through IoC.Get<> to get the instances of my view Models, I think it violates the principles of IoC if I am not mistaken. In a few other examples, they create new viewModels when needed, but what's the point of using IoC in that case, especially when I need services injected inside those new ViewModels?
在我的Shell视图中,我有一个包含3个不同区域的布局,通过以下方式绑定到我的Shell视图模型:
In my Shell view, I have a layout with 3 different areas, bound to my shell view model by :
<ContentControl x:Name="Header"
Grid.ColumnSpan="3"/>
<ContentControl x:Name="Menu"
Grid.Row="1"/>
<ContentControl x:Name="Main"
Grid.ColumnSpan="3"/>
在我的ShellViewModel扩展Conductor.Collection.AllActive中,我引用了以下3个区域:
In my ShellViewModel extending Conductor.Collection.AllActive, I reference the 3 areas like this:
public Screen Menu { get; private set; }
public Screen Header { get; private set; }
public Screen Main { get; private set; }
我希望能够像这样更改它们:
I would like to be able to change them like so:
Menu = Items.FirstOrDefault(x => x.DisplayName == "Menu");
Header = Items.FirstOrDefault(x => x.DisplayName == "Header");
Main = Items.FirstOrDefault(x => x.DisplayName == "Landing");
我所有的ViewModel的构造函数中都设置了DisplayName。
All my ViewModels have a DisplayName set in their constructor.
我已经尝试过,但是GetChildren()为空
I have tried this but GetChildren() is empty
foreach (var screen in GetChildren())
{
Items.Add(screen);
}
我错过了明显的东西吗?
Am I missing something obvious?
谢谢!
推荐答案
最后,我设法自己找到了答案。
Finally, I managed to find an answer myself. It's all in the AppBootstrapper!
我最终为我的屏幕创建了一个ViewModelBase,以便它们都可以具有IShell属性(以便ViewModels可以在ShellViewModel)像这样:
I ended up creating a ViewModelBase for my Screens so that they could all have an IShell property (so that the ViewModels could trigger a navigation in the ShellViewModel) like so:
public class ViewModelBase : Screen
{
private IShell _shell;
public IShell Shell
{
get { return _shell; }
set
{
_shell = value;
NotifyOfPropertyChange(() => Shell);
}
}
}
然后在AppBoostrapper中进行注册像这样:
then in the AppBoostrapper registered them like this :
container.Singleton<ViewModelBase, SomeViewModel>();
container.Singleton<ViewModelBase, AnotherViewModel>();
container.Singleton<ViewModelBase, YetAnotherViewModel>();
然后创建一个IEnumerable作为参数传递给我的ShellViewModel ctor:
then created an IEnumerable to pass as param to my ShellViewModel ctor:
IEnumerable<ViewModelBase> listScreens = GetAllScreenInstances();
container.Instance<IShell>(new ShellViewModel(listScreens));
然后将IShell传递给每个ViewModel
then passing the IShell to each ViewModels
foreach (ViewModelBase screen in listScreens)
{
screen.Shell = GetShellViewModelInstance();
}
为了完整起见,这是我的GetAllScreenInstances()和GetShellViewModelInstance() :
for the sake of completeness, here are my GetAllScreenInstances() and GetShellViewModelInstance() :
protected IEnumerable<ViewModelBase> GetAllScreenInstances()
{
return container.GetAllInstances<ViewModelBase>();
}
protected IShell GetShellViewModelInstance()
{
var instance = container.GetInstance<IShell>();
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
这是我的ShellViewModel ctor的样子:
Here's what my ShellViewModel ctor looks like:
public ShellViewModel(IEnumerable<ViewModelBase> screens )
{
Items.AddRange(screens);
}
希望这对以后的人有帮助!
Hope this can help someone in the future!
这篇关于ShellViewModel Caliburn.Micro中的ViewModels参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!