ShellViewModel Caliburn.Micro中的ViewModels参考 [英] ViewModels references in ShellViewModel Caliburn.Micro

查看:113
本文介绍了ShellViewModel Caliburn.Micro中的ViewModels参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此线程中:有人能提供导体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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆