我正在尝试在MVVM项目中实现notifyicon(http://www.hardcodet.net/projects/wpf-notifyicon)。我知道这个控件适用于常规的WPF项目。
我想知道如何实现气球功能(Balloon feature)。 如本教程中所述,需要调用方法“ShowBallonTip”
//show balloon with built-in icon
MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
我能想到的唯一可以调用此方法的地方就是代码背后的代码。我在后面的视图代码中有一些代码没有问题(即使我不想有任何代码),但我无法弄清楚如何让视图模型与视图对话并要求它调用此方法方法
即使我将此方法放在一个事件中,如何以编程方式从视图模型中提取此事件?
知道如何实现这个目标吗?
答案 0 :(得分:2)
我发现了一个不那么明显的解决方案,但可以说与MVVM模式更合适。它允许在XAML中创建TaskbarIcon并通过ViewModel提供新的气球数据。
首先要做的是添加某种能力来通知TaskbarIcon,我们希望它显示一个泡泡,我选择使用Microsofts Rx Extensions(NuGet Package Rx-Main)来处理这个问题,但任何合适的基础设施都可以使用。这是新的TaskbarIcon类,以及一个用于保存我们想要在调用ShowBubbleTip方法时传递的数据的类。
using Hardcodet.Wpf.TaskbarNotification;
using System;
using System.Windows;
namespace Phi.Utility
{
public class TaskbarIconRxBallonNotification
{
public Hardcodet.Wpf.TaskbarNotification.BalloonIcon Icon
{
get;
private set;
}
public string BallonTitle
{
get;
private set;
}
public string Message
{
get;
private set;
}
public TaskbarIconRxBallonNotification(Hardcodet.Wpf.TaskbarNotification.BalloonIcon icon, string balloonTitle, string message)
{
Icon = icon;
BallonTitle = balloonTitle;
Message = message;
}
}
public class TaskbarIconRx : TaskbarIcon
{
public IObservable<TaskbarIconRxBallonNotification> BalloonTipNotifier
{
get { return (IObservable<TaskbarIconRxBallonNotification>)GetValue(BallonTipNotifierProperty); }
set { SetValue(BallonTipNotifierProperty, value); }
}
// Using a DependencyProperty as the backing store for BalloonSubject. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BallonTipNotifierProperty =
DependencyProperty.Register("BalloonTipNotifier", typeof(IObservable<TaskbarIconRxBallonNotification>), typeof(TaskbarIconRx), new PropertyMetadata(null, BallonTipNotifierChanged));
//What to do when we get a new ballonIcon request
protected void OnNextNotification(TaskbarIconRxBallonNotification notification)
{
ShowBalloonTip("", notification.Message, BalloonIcon.Info);
}
private IDisposable _subscription;
//Make sure swapping out bindings doesn't break our program.
public static void BallonTipNotifierChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TaskbarIconRx currentNotifier = d as TaskbarIconRx;
if (currentNotifier != null)
{
IObservable<TaskbarIconRxBallonNotification> prev = e.OldValue as IObservable<TaskbarIconRxBallonNotification>;
IObservable<TaskbarIconRxBallonNotification> next = e.NewValue as IObservable<TaskbarIconRxBallonNotification>;
if (currentNotifier._subscription != null)
{
currentNotifier._subscription.Dispose();
currentNotifier._subscription = null;
}
if ((next != null))
{
currentNotifier._subscription = next.Subscribe(currentNotifier.OnNextNotification);
}
}
}
}
}
在我们的模型中,我们提供了一个绑定到
的ISubjectusing System.Reactive.Subjects;
namespace Phi.Models {
public class SomeModel:ModelBase {
public ISubject<Utility.TaskbarIconRxBallonNotification> NotifierInterface
{
get;
private set;
}
public SomeModel() {
NotifierInterface = new Subject<Utility.TaskbarIconRxBallonNotification>();
}
}
}
在我们的ViewModel中,我们现在可以通过模型主题推送通知,如下所示:
namespace Phi.ViewModels{
public class SomeViewModel:ViewModelBase
{
public SomeModel Model{
get;
private set;
}
public void PushNotification(string message)
{
//Pushes a new notification to the TaskbarIcon.
Model.NotifierInterface.OnNext(new Utility.TaskbarIconRxBallonNotification(Hardcodet.Wpf.TaskbarNotification.BalloonIcon.Info, "Title", message));
}
}
}
在XAML中,我们绑定到我们的模型ISubject
<Utility:TaskbarIconRx Visibility= IconSource="/Resources/TinyLogo.ico" BalloonTipNotifier="{Binding Model.NotifierInterface}" >
答案 1 :(得分:1)
我已经能够通过初始化视图模型中的图标而不是XAML来显示气球提示。
只需在我的命令中调用ShowBalloonTip方法即可。
我为通知图标创建了一个包装器: NotifyService:
public class NotifyService : INotifyService
{
private TaskbarIcon icon = new TaskbarIcon
{
Name = "NotifyIcon",
Icon =
new System.Drawing.Icon(
Application.GetResourceStream(Utils.FileUtils.MakeUri("/Icons/email.ico")).Stream),
};
public void Notify(string message)
{
icon.ShowBalloonTip("title", message, BalloonIcon.None);
}
public void ChangeIconSource(string path)
{
icon.Icon = new System.Drawing.Icon(
Application.GetResourceStream(Utils.FileUtils.MakeUri(path)).Stream);
}
}
我在我的视图模型中使用它: 视图模型
public class MainWindowViewModel : WindowViewModelBase
{
private readonly INotifyService notifyService = new NotifyService();
#region Fields
private static HomeWindowViewModel homeViewModel = new HomeWindowViewModel();
#endregion
/// Initializes a new instance of the <see cref="MainWindowViewModel"/> class.
/// </summary>
public MainWindowViewModel()
: base()
{
CurrentViewModel = homeViewModel;
}
#region Methods
protected override void OnViewModelPropertyChanged(IViewModel viewModel, string propertyName)
{
int t = 2;
}
protected override void OnViewModelCommandExecuted(IViewModel viewModel, ICatelCommand command, object commandParameter)
{
int t = 2;
notifyService.ChangeIconSource(@"/Icons/new_email.ico");
notifyService.Notify("test");
}
#endregion
}
答案 2 :(得分:0)
TaskbarIcon MyNotifyIcon = new TaskbarIcon();
private void ShowStandardBalloon()
{
if (ping == false)
{
string title = "Website is offline!";
string text = Url;
MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
}else if(ping == true)
{
string title = "Website is online!";
string text = Url;
MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Info);
}
}
将其粘贴到ViewModel中并更改值,并准备好了。只需调用ShowStandartBallon();并且你在Code Behind中没有代码。
[编辑]
TaskbarIcon MyNotifyIcon = new TaskbarIcon();
private void ShowStandardBalloon()
{
string title = "Website is offline!";
string text = Url; //Url is a String
MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
}
答案 3 :(得分:0)
只需在视图中使用绑定到VM中实例化的TaskbarIcon对象的ContentControl。然后将命令直接发送到VM中的对象。
XAML:
<ContentControl Content="{Binding NotifyIcon}"/>
代码:
private TaskbarIcon notifyIcon;
public TaskbarIcon NotifyIcon
{
get { return notifyIcon; }
set { notifyIcon = value; OnPropertyChanged("NotifyIcon"); }
}
private void ShowBalloon()
{
NotifyIcon.ShowBalloonTip("Hi", "Some info here.", BalloonIcon.Info);
}