代码之家  ›  专栏  ›  技术社区  ›  styx

类型不包括任何可访问的构造函数wpf-无窗口应用程序

  •  0
  • styx  · 技术社区  · 5 年前

    我在用 this 用于创建和使用通知图标的包,这意味着我的应用程序中没有窗口 ResourceDictionary ViewModel

    在我更改构造函数以接受使用DI框架的接口(我正在使用 自动对焦 Prism的扩展[prism.autopac])。

    如果我添加回无参数构造函数,一切都会正常工作

    我要用自动空调吗?太过分了。我怎么做DI?

    笔记

    代码文件

        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);
            }
        }
    

    应用.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>
    

    引导程序.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 回复  |  直到 5 年前
        1
  •  1
  •   BionicCode    5 年前

    它不起作用,因为您正在设置 ObjectDataProvider 实例到 DataContext

    <tb:TaskbarIcon.DataContext>
        <ObjectDataProvider ObjectType="{x:Type local:NotifyIconViewModel}">
            <ObjectDataProvider.ConstructorParameters>
                <interface:ServiceControllerWorker />
            </ObjectDataProvider.ConstructorParameters>
        </ObjectDataProvider>
    </tb:TaskbarIcon.DataContext>
    

    而不是 价值 对象数据提供程序 .
    在中声明提供程序 ResourceDictionary :

    <ResourceDictionary>    
        <ObjectDataProvider x:Key="ViewModelProvider" ObjectType="{x:Type local:NotifyIconViewModel}">
            <ObjectDataProvider.ConstructorParameters>
                <interface:ServiceControllerWorker />
            </ObjectDataProvider.ConstructorParameters>
        </ObjectDataProvider>
    </ResourceDictionary>
    

    把它绑在 数据上下文 :

    <tb:TaskbarIcon DataContext="{Binding Source={StaticResource ViewModelProvider}}" />
    

    绑定将使提供程序实例化所提供的实例。

    但由于您是在 对象数据提供程序 您使autopac容器或依赖项注入冗余。如果要使用依赖项注入,必须允许autopac创建实例。这要求手动启动应用程序并重写 MainWindow 或者主机 Window TaskbarIcon 使用合成:

    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;      
        }
    }
    

    在mainwindow.xaml中,将属性绑定到 ContentPresenter :

    <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();
        }
    }
    

    然后引导应用程序:

    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();         
        }
    }
    

    这样你就摆脱了 对象数据提供程序 ,因为您使用的是自动对焦。