简体   繁体   English

从资源加载任务栏图标并使用 Prism 注入视图 model

[英]Loading a Taskbar Icon from resources and using Prism to inject view model

Background背景

I am trying to write an application which primarily lives on the system tray, it will in the future have a window so on right clicking the icon it opens the window.我正在尝试编写一个主要存在于系统托盘上的应用程序,它将来有一个 window 所以右键单击它打开 window 的图标。

The Code编码

I currently have no shell being defined on Prism startup ie:我目前没有在 Prism 启动时定义 shell,即:

protected override Window CreateShell()
{
    return null;
}

The notify icon (using Hardcodet.NotifyIcon if that makes any difference?) is defined in a resources dictionary, as i don't have a startup View xaml to add the icon to:通知图标(使用Hardcodet.NotifyIcon是否有任何区别?)在资源字典中定义,因为我没有启动视图xaml 以将图标添加到:

<!-- the application's NotifyIcon - started from App.xaml.cs. Declares its own view model. -->
    <tb:TaskbarIcon x:Key="NotifyIcon"
                    IconSource="{Binding UserStatus, Converter={StaticResource UserStatusToImageSourceConverter}}"
                    ToolTipText="Double-click for window, right-click for menu"
                    DoubleClickCommand="{Binding ShowWindowCommand}"
                    ContextMenu="{StaticResource SysTrayMenu}">

         <!--self-assign a data context (could also be done programmatically)--> 
        <tb:TaskbarIcon.DataContext>
            <viewModels:NotifyIconViewModel />
        </tb:TaskbarIcon.DataContext>
    </tb:TaskbarIcon>

The view model, as you can see on the later part of that snippet, takes the NotifyIconViewModel , which has a constructor argument so I can use the IEventAggregator to communicate between the different parts of views (like a view in the context menu shown when you just plain click on the tray icon).视图 model,正如您在该片段的后面部分看到的那样,采用NotifyIconViewModel ,它有一个构造函数参数,因此我可以使用IEventAggregator在视图的不同部分之间进行通信(就像当您显示的上下文菜单中的视图只需单击托盘图标)。

The signature of the view model looks like so:视图 model 的签名如下所示:

public NotifyIconViewModel(IEventAggregator eventAggregator)
{
    _eventAggregator = eventAggregator;
    ...
}

The services are registered:服务已注册:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    ...
    containerRegistry.Register<NotifyIconViewModel>();
}

And the Notify Icon itself is instantiated in the OnInitialized Method:而通知图标本身是在OnInitialized方法中实例化的:

protected override void OnInitialized()
{
    base.OnInitialized();
    notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
}

The Issue问题

However, the exception being thrown on startup is that no default constructor could be found for the view model (correct, there isnt one).但是,启动时抛出的异常是没有为视图 model 找到默认构造函数(正确,没有)。 But my reading is that the prism architecture should be able to inject the view model (and its deps) when required?但我的阅读是棱镜架构应该能够在需要时注入视图 model (及其部门)?

XamlParseException

I can only assume I am initializing the notify icon incorrectly and that FindResource does not cause the prism library constructor injection/DI parts to be triggered, but what would the correct way for this behaviour to be carried out be?我只能假设我错误地初始化了通知图标,并且 FindResource 不会导致触发 prism 库构造函数注入/DI 部分,但是执行此行为的正确方法是什么?

Dependencies are injected if you use the container to construct (aka. resolve) the object.如果您使用容器构造(也称为解析)object,则会注入依赖项。

This happens when a normal Prism application resolves the shell, which (by using the ViewModelLocator ) resolves the shell's view model which resolves alle the dependencies of the shell's view model and the dependencies of those dependencies and so on. This happens when a normal Prism application resolves the shell, which (by using the ViewModelLocator ) resolves the shell's view model which resolves alle the dependencies of the shell's view model and the dependencies of those dependencies and so on.

If you do not use the container (ie by constructing objects directly in xaml), it won't resolve any dependencies for you.如果您使用容器(即直接在 xaml 中构造对象),它不会为您解决任何依赖关系。

You could create the icon and use the container to resolve the NotifyIconViewModel and set it as DataContext :您可以创建图标并使用容器来解析NotifyIconViewModel并将其设置为DataContext

protected override void OnInitialized()
{
    base.OnInitialized();
    notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
    notifyIcon.DataContext = Container.Resolve<NotifyIconViewModel>();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM