I found a less obvious solution, but one that arguably fit's better with the MVVM pattern. It allows the TaskbarIcon to be created in XAML and fed new balloon data by the ViewModel.
The first thing to do is add some sort of ability to notify the TaskbarIcon we want it to show a bubble I chose to use Microsofts Rx Extensions (NuGet Package Rx-Main) for this purpouse, but any suitable infrastructure will work. This is the new TaskbarIcon class, and a class for holding the data we would like to pass when the ShowBubbleTip method is called.
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);
}
}
}
}
}
In our Model, we provide an ISubject to bind to
using 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>();
}
}
}
In our ViewModel, we can now push notifications through the models subject, like so:
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));
}
}
}
and in the XAML, we bind to our models ISubject
<Utility:TaskbarIconRx Visibility= IconSource="/Resources/TinyLogo.ico" BalloonTipNotifier="{Binding Model.NotifierInterface}" >