我正在使用this包来创建和使用通知图标,这意味着我的应用程序中仅ResourceDictionary
和ViewModel
中没有Windows
一切正常,直到我更改构造函数以使用DI框架接受接口为止(我正在使用 Autofac 对PRISM [Prism.Autofac]的扩展)。
如果我重新添加无参数构造函数,那么一切都会很好
我应该使用Autofac还是太过分了?我怎么做DI?
注释
ObjectDataProvider
文档,找不到任何解决方案App.xaml.cs
public partial class App : Application
{
private TaskbarIcon notifyIcon;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new Bootstrapper();
bootstrapper.Run();
notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
}
protected override void OnExit(ExitEventArgs e)
{
notifyIcon.Dispose();
base.OnExit(e);
}
}
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="NotifyIconResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
NotifyIconResources.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
xmlns:local ="clr-namespace:WatchDog"
xmlns:interface="clr-namespace:ServiceControllerLibary;assembly=ServiceControllerLibary"
>
<local:ServiceControllerWorkerStatusToIconConverter x:Key="ServiceControllerWorkerStatusToIconConverter"/>
<ContextMenu x:Shared="false" x:Key="SysTrayMenu">
<MenuItem Header="Show Window" />
<MenuItem Header="Hide Window" />
<Separator />
<MenuItem Header="Exit" />
</ContextMenu>
<tb:TaskbarIcon x:Key="NotifyIcon"
ToolTipText ="{Binding ToolTipText}" DoubleClickCommand="{Binding}"
ContextMenu="{StaticResource SysTrayMenu}"
IconSource="{Binding ToolTipStatus,
Converter={StaticResource ServiceControllerWorkerStatusToIconConverter}
, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<!-- Original Not Working-->
<!-- self-assign a data context (could also be done programmatically) -->
<!--<tb:TaskbarIcon.DataContext>
<local:NotifyIconViewModel/>
</tb:TaskbarIcon.DataContext>-->
<!-- 2nd try Not Working-->
<tb:TaskbarIcon.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:NotifyIconViewModel}">
<ObjectDataProvider.ConstructorParameters>
<interface:ServiceControllerWorker />
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</tb:TaskbarIcon.DataContext>
</tb:TaskbarIcon>
</ResourceDictionary>
Bootstrapper.cs
class Bootstrapper : AutofacBootstrapper
{
protected override void ConfigureContainerBuilder(ContainerBuilder builder)
{
base.ConfigureContainerBuilder(builder);
builder.RegisterType<ServiceControllerWorker>().As<IServiceControllerWorker>().SingleInstance();
}
}
NotifyIconViewModel.cs(仅限构造函数)
public NotifyIconViewModel(IServiceControllerWorker ServiceControllerWorker)
{
_serviceControllerWorker = ServiceControllerWorker;
}
答案 0 :(得分:1)
它不起作用,因为您将ObjectDataProvider
实例设置为DataContext
<tb:TaskbarIcon.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:NotifyIconViewModel}">
<ObjectDataProvider.ConstructorParameters>
<interface:ServiceControllerWorker />
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</tb:TaskbarIcon.DataContext>
代替ObjectDataProvider
的值。
在ResourceDictionary
中声明提供者:
<ResourceDictionary>
<ObjectDataProvider x:Key="ViewModelProvider" ObjectType="{x:Type local:NotifyIconViewModel}">
<ObjectDataProvider.ConstructorParameters>
<interface:ServiceControllerWorker />
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</ResourceDictionary>
并将其绑定到DataContext
:
<tb:TaskbarIcon DataContext="{Binding Source={StaticResource ViewModelProvider}}" />
绑定将使提供程序实例化所提供的实例。
但是,由于要在ObjectDataProvider
的帮助下创建实例,因此使Autofac容器或依赖项注入变得多余。如果要使用依赖项注入,则必须让Autofac创建实例。这要求应用程序手动启动,并重写MainWindow
的{{1}}或托管Window
才能使用组合:
TaskbarIcon
在MainWindow.xaml中,将该属性绑定到public partial class MainWindow : Window
{
public static readonly DependencyProperty NotifyIconProperty = DependencyProperty.Register(
"NotifyIcon",
typeof(TaskbarIcon),
typeof(Window),
new PropertyMetadata(default(TaskbarIcon)));
public TaskbarIcon NotifyIcon { get { return (TaskbarIcon) GetValue(MainWindow.NotifyIconProperty); } set { SetValue(MainWindow.NotifyIconProperty, value); } }
public MainWindow(TaskbarIcon taskbarIcon, INotifyIconViewModel notifyIconDataContext, IViewModel dataContext)
{
this.notifyIcon = taskbarIcon;
this.notifyIcon.DataContext = notifyIconDataContext;
this.DataContext = dataContext;
}
}
:
ContentPresenter
然后配置Autofac容器:
<Window>
<ContentPresenter Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=MainWindow}, Path=NotifyIcon} />
</Window>
然后引导应用程序:
class Bootstrapper : AutofacBootstrapper
{
public Container ConfigureContainerBuilder()
{
var builder = new ContainerBuilder();
builder.RegisterType<ServiceControllerWorker>().As<IServiceControllerWorker>().SingleInstance();
builder.RegisterType<NotifyIconViewModel>().As<INotifyIconViewModel>().SingleInstance();
builder.RegisterType<TaskbarIcon>().SingleInstance();
builder.RegisterType<MainWindow>().SingleInstance();
return builder.Build();
}
}
由于您使用的是Autofac,因此您摆脱了public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new Bootstrapper();
var container = bootstrapper.ConfigureContainerBuilder();
Application.Current.MainWindow = container.Resolve<MainWindow>();
Application.Current.MainWindow.Show();
}
}
。