我试图让Hardcodet的WPF NotifyIcon在WPF应用程序中工作,但结果却很奇怪。
目标如下:
正在使用的库:
首先,我想发布没有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天的反复试验,但无济于事。