带有NotifyIcon.WPF的Caliburn Micro,多个托盘图标和绑定失败

时间:2018-08-02 18:42:43

标签: c# wpf mvvm caliburn.micro notifyicon

我试图让Hardcodet的WPF NotifyIcon在WPF应用程序中工作,但结果却很奇怪。

目标如下:

  • MainViewModel从EventAggregator接收通知
  • MainViewModel使用ShowBaloonTip显示通知消息

正在使用的库:

  • Caliburn.Micro
  • Hardcodet.NotifyIcon.WPF
  • Autofac
  • Caliburn.Micro.AutofacBootstrap
  • MaterialDesignThemes

首先,我想发布没有BalloonTip实现的NotifyIcon的实现。效果很好,这里没有问题:

MainView.xaml

<Window.Resources>
    <ContextMenu x:Shared="false" x:Key="MainSysTrayMenu">
        <MenuItem Header="Quick Status" cal:Message.Attach="OpenStatusWindow()" IsEnabled="{Binding Path=CanOpenStatusWindow, Mode=OneWay}" />
        <MenuItem Header="Details" cal:Message.Attach="OpenDetailWindow()" IsEnabled="{Binding Path=CanOpenDetailWindow, Mode=OneWay}" />
        <MenuItem Header="About" cal:Message.Attach="OpenAboutWindow()" IsEnabled="{Binding Path=CanOpenAboutWindow, Mode=OneWay}" />
        <Separator />
        <MenuItem Header="Exit" cal:Message.Attach="ExitApplication()" />
    </ContextMenu>
    <tb:TaskbarIcon x:Key="SystemTrayIcon"
                    IconSource="/Resources/NotifyIcons/Red.ico"
                    ToolTipText="Double-click for window, right-click for menu"
                    cal:Message.Attach="[Event TrayMouseDoubleClick] = [Action OpenStatusWindow]"
                    Visibility="Visible"
                    ContextMenu="{StaticResource MainSysTrayMenu}" >
        <tb:TaskbarIcon.TrayToolTip>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center"
                        Background="White"
                        BorderBrush="DeepSkyBlue"
                        BorderThickness="2"
                        CornerRadius="4"
                        Opacity="0.95"
                        Width="165"
                        Height="40">
                    <TextBlock Text="{Binding Path=StatusToolTipText, Mode=OneWay}" 
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Foreground="Black"
                               FontFamily="{DynamicResource MaterialDesignFont}"
                    />
                </Border>
            </Grid>
        </tb:TaskbarIcon.TrayToolTip>
    </tb:TaskbarIcon>
</Window.Resources>
<Grid>
    <TextBlock>View + ViewModel started from bootstrapper. This should not be visible.</TextBlock>
    <ContentControl >
        <Label x:Name="TestString" Content="Label" HorizontalAlignment="Left" Margin="111,83,0,0" VerticalAlignment="Top"/>
    </ContentControl>
    <ContentControl Content="{StaticResource SystemTrayIcon}" />
</Grid>

MainViewModel

public MainViewModel(IWindowManager windowManager, IEventAggregator eventAggregator, StatusViewModel statusViewModel,
        DetailViewModel detailViewModel, AboutViewModel aboutViewModel)
    {
        _windowManager = windowManager;
        _eventAggregator = eventAggregator;
        _eventAggregator.Subscribe(this);
        _statusViewModel = statusViewModel;
        _detailViewModel = detailViewModel;
        _aboutViewModel = aboutViewModel;
        _statusToolTipText = "SOC: 0% | RTE: 0min";
        LaunchManager();
    }

以及MainView中使用的ViewModel的辅助功能

 public bool CanOpenStatusWindow => !_statusViewModel.IsActive;
    public bool CanCloseStatusWindow => _statusViewModel.IsActive;

    public void OpenStatusWindow()
    {
        _windowManager.ShowWindow(_statusViewModel);
        NotifyOfPropertyChange(() => CanOpenStatusWindow);
        NotifyOfPropertyChange(() => CanCloseStatusWindow);

    }

这是三个窗口中每个窗口的重复项,非常标准。

NotifyIcon“ MVVM”实现

这就是事情变得艰难的地方。在Hardcodet的示例代码中,绑定是这样完成的:

<tb:TaskbarIcon IconSource="/Icons/Inactive.ico"
                    ToolTipText="{Binding Timestamp}">
        <tb:TaskbarIcon.TrayPopup >
            <!-- the popup, here a custom user control, will also get the DataContext of the NotifyIcon -->
            <local:ClockPopup Opacity="0.8" />
        </tb:TaskbarIcon.TrayPopup>
    </tb:TaskbarIcon>

我的意图是将此TaskbarIcon绑定到NotifyIcon。我无法使该实现与​​StaticResource一起使用,因此将整个块都放入了MainWindow.xaml页面:

MainView.xaml

<tb:TaskbarIcon x:Name="NotifyIcon"
                    IconSource="/Resources/NotifyIcons/Red.ico"
                    ToolTipText="Double-click for window, right-click for menu"
                    cal:Message.Attach="[Event TrayMouseDoubleClick] = [Action OpenStatusWindow]"
                    Visibility="Visible">
        <tb:TaskbarIcon.ContextMenu>
            <ContextMenu DataContext="{Binding}">
                <MenuItem Header="Quick Status" cal:Message.Attach="OpenStatusWindow()" IsEnabled="{Binding Path=CanOpenStatusWindow, Mode=OneWay}" />
                <MenuItem Header="Details" cal:Message.Attach="OpenDetailWindow()" IsEnabled="{Binding Path=CanOpenDetailWindow, Mode=OneWay}" />
                <MenuItem Header="About" cal:Message.Attach="OpenAboutWindow()" IsEnabled="{Binding Path=CanOpenAboutWindow, Mode=OneWay}" />
                <Separator />
                <MenuItem Header="Exit" cal:Message.Attach="ExitApplication()" />
            </ContextMenu>
        </tb:TaskbarIcon.ContextMenu>
        <tb:TaskbarIcon.TrayToolTip>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center"
                        Background="White"
                        BorderBrush="DeepSkyBlue"
                        BorderThickness="2"
                        CornerRadius="4"
                        Opacity="0.95"
                        Width="165"
                        Height="40">
                    <TextBlock Text="{Binding Path=StatusToolTipText, Mode=OneWay}" 
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Foreground="Black"
                               FontFamily="{DynamicResource MaterialDesignFont}"
                    />
                </Border>
            </Grid>
        </tb:TaskbarIcon.TrayToolTip>
    </tb:TaskbarIcon>

MainViewModel.xaml

 private NotifyIcon _notifyIcon;

    public NotifyIcon NotifyIcon
    {
        get => _notifyIcon;
        set
        {
            _notifyIcon = value;
            NotifyOfPropertyChange();
        }
    }

    public MainViewModel(IWindowManager windowManager, IEventAggregator eventAggregator,
        StatusViewModel statusViewModel,
        DetailViewModel detailViewModel, AboutViewModel aboutViewModel)
    {
        _notifyIcon = new NotifyIcon();
        _notifyIcon.BalloonTipText = "test";
        _notifyIcon.ShowBalloonTip(3000);
    }

以下操作无效,因此我尝试了一些在网站上发现的实现,但均无济于事。此页面:How to integrate WPF NotifyIcon with Caliburn.Micro由于年龄较大而无法正常工作(NotifyIcon是他们在文档中推荐的用法,而不是TaskbarIcon)。使它运行会导致循环序列,从而打开大量的托盘图标。

使用图标,上下文菜单,文本正确实例化_notifyIcon实际上会导致创建两个任务栏。一个带有我好的任务栏和菜单,一个带有ViewModel中制作的。

任何帮助将不胜感激,我唯一的目标是保留菜单在 MaterialView.xaml 中定义的菜单,但是能够针对不同的连接状态等触发BallonTip通知。

感谢您的帮助并阅读了所有这些内容,我给了它大约3天的反复试验,但无济于事。

0 个答案:

没有答案
相关问题