下面是WPF实现托盘的完整攻略:
一、前期准备
在开始编写代码之前,首先需要在项目中添加两个NuGet包:
- Hardcodet.NotifyIcon.Wpf(用于实现托盘功能)
- System.Windows.Interactivity.Wpf(用于方便地实现交互行为,如点击托盘图标时打开窗口)
这两个包的添加方式可以通过NuGet包管理器或在项目文件中手动添加。
二、定义托盘图标和菜单
在主窗口中添加托盘图标,并在托盘图标的上下文菜单中添加菜单项,可以通过以下代码实现:
<Window ...>
...
<Window.Resources>
<tray:TaskbarIcon x:Key="NotifyIcon" IconSource="icon.ico">
<tray:TaskbarIcon.ContextMenu>
<ContextMenu>
<MenuItem Header="打开窗口" Command="{Binding OpenWindowCommand}" />
<Separator />
<MenuItem Header="退出" Command="{Binding ExitCommand}" />
</ContextMenu>
</tray:TaskbarIcon.ContextMenu>
</tray:TaskbarIcon>
</Window.Resources>
...
</Window>
上述代码中,tray
是指向Hardcodet.NotifyIcon.Wpf命名空间的XAML命名空间,icon.ico
是托盘图标的路径。同时,在托盘图标的上下文菜单中定义了两个菜单项,分别绑定到主窗口ViewModel中的OpenWindowCommand
和ExitCommand
命令。
三、实现托盘功能
在主窗口ViewModel中,实现托盘功能需要完成以下几个步骤:
- 定义一个NotifyIcon对象,并在视图中绑定到托盘图标。
public class MainViewModel : INotifyPropertyChanged
{
...
private readonly NotifyIcon _notifyIcon;
public MainViewModel()
{
_notifyIcon = (NotifyIcon)Application.Current.FindResource("NotifyIcon");
...
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
...
}
在ViewModel的构造函数中获取在视图中定义的NotifyIcon对象,并保存到一个私有字段,以便后续使用。
- 定义OpenWindowCommand和ExitCommand命令,并实现相应的功能。
public class MainViewModel : INotifyPropertyChanged
{
...
public ICommand OpenWindowCommand => new DelegateCommand(() =>
{
// 显示或激活主窗口
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
{
mainWindow.Show();
if (mainWindow.WindowState == WindowState.Minimized)
{
mainWindow.WindowState = WindowState.Normal;
}
mainWindow.Activate();
}
});
public ICommand ExitCommand => new DelegateCommand(() =>
{
// 关闭应用程序
Application.Current.Shutdown();
});
...
}
上述代码中,OpenWindowCommand
命令用于打开或激活主窗口,ExitCommand
命令用于退出应用程序。
- 添加对WindowState的监听,实现窗口最小化时隐藏窗口并显示托盘图标。
public class MainViewModel : INotifyPropertyChanged
{
...
public MainViewModel()
{
_notifyIcon = (NotifyIcon)Application.Current.FindResource("NotifyIcon");
...
// 添加对WindowState的监听
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
{
mainWindow.StateChanged += (sender, e) =>
{
switch (mainWindow.WindowState)
{
case WindowState.Minimized:
mainWindow.Hide();
_notifyIcon.ShowBalloonTip("提示", "应用程序已最小化到托盘", BalloonIcon.Info);
break;
case WindowState.Normal:
_notifyIcon.HideBalloonTip();
break;
}
};
}
}
...
}
在构造函数中获取主窗口对象,并添加对WindowState的监听。当窗口状态变为最小化时,隐藏窗口并显示一个气泡提示,提醒用户应用程序已经最小化到托盘。
- 实现托盘图标的交互行为,如右键菜单打开主窗口。
public class MainViewModel : INotifyPropertyChanged
{
...
public MainViewModel()
{
...
// 实现交互行为
Interaction.GetBehaviors(_notifyIcon).Add(new TaskbarIconBehavior(OpenWindowCommand));
}
...
}
public class TaskbarIconBehavior : Behavior<NotifyIcon>
{
private readonly ICommand _command;
public TaskbarIconBehavior(ICommand command)
{
_command = command;
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TrayMouseDoubleClick += AssociatedObjectOnTrayMouseDoubleClick;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.TrayMouseDoubleClick -= AssociatedObjectOnTrayMouseDoubleClick;
}
private void AssociatedObjectOnTrayMouseDoubleClick(object sender, RoutedEventArgs e)
{
_command.Execute(null);
}
}
在主窗口ViewModel中,通过Behavior
将托盘图标的交互行为定义为一个类,该类实现OnAttached
、OnDetaching
等相关方法,将双击图标打开主窗口的逻辑绑定到OpenWindowCommand
命令上。
至此,WPF实现托盘的工作完毕。
四、示例说明
- 如何使用NotifyIcon显示气泡提示?
可以通过ShowBalloonTip
方法显示气泡提示,方法参数包括提示标题、提示消息和提示图标。例如:
_notifyIcon.ShowBalloonTip("提示", "这是一条气泡提示", BalloonIcon.Info);
- 如何在托盘图标上添加自定义图标?
可以通过在托盘图标的XAML中指定IconSource
属性实现自定义图标。例如:
<tray:TaskbarIcon IconSource="my_icon.ico">
其中my_icon.ico
是自定义图标的文件名。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:WPF实现基础控件之托盘的示例代码 - Python技术站