如何在MVVM项目中实现notifyicon

如何在MVVM项目中实现notifyicon,mvvm,notifyicon,Mvvm,Notifyicon,我试图在MVVM项目中实现notifyicon()。我理解这个控件是为了在常规WPF项目中使用 我想知道如何实现ballon特性()。 如本教程所述,需要调用方法“ShowBallonTip” //show balloon with built-in icon MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Error); 我能想到的唯一可以调用这个方法的地方就是代码背后。在视图代码隐藏中有一点代码(即使我不希望有代码隐藏),我没有

我试图在MVVM项目中实现notifyicon()。我理解这个控件是为了在常规WPF项目中使用

我想知道如何实现ballon特性()。 如本教程所述,需要调用方法“ShowBallonTip”

//show balloon with built-in icon
  MyNotifyIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
我能想到的唯一可以调用这个方法的地方就是代码背后。在视图代码隐藏中有一点代码(即使我不希望有代码隐藏),我没有问题,但我无法弄清楚如何让视图模型与视图对话,并要求它调用此方法

即使将此方法放置在事件中,如何从viewmodel以编程方式引发此事件


你知道我怎样才能做到这一点吗?

我已经能够通过初始化viewmodel中的图标而不是XAML来显示气球提示

只需在我的命令中调用showBalloadTip方法即可

我为通知图标创建了一个包装: 通知服务:

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
}
公共类MainWindowViewModel:WindowViewModelBase { private readonly INotifyService notifyService=new notifyService(); #区域字段 私有静态HomeWindowViewModel homeViewModel=新HomeWindowViewModel(); #端区 ///初始化类的新实例。 /// 公共主窗口视图模型() :base() { CurrentViewModel=homeViewModel; } #区域方法 受保护的覆盖无效OnViewModelPropertyChanged(IViewModel viewModel,字符串propertyName) { int t=2; } 已执行受保护的覆盖void OnViewModelCommandExecuted(IViewModel viewModel、ICatelCommand命令、对象commandParameter) { int t=2; notifyService.ChangeIconSource(@“/Icons/new_email.ico”); notifyService.Notify(“测试”); } #端区 }
我发现了一个不太明显的解决方案,但可以说更适合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);
                }
            }
        }

    }
}
在XAML中,我们绑定到我们的模型是subject

<Utility:TaskbarIconRx Visibility= IconSource="/Resources/TinyLogo.ico" BalloonTipNotifier="{Binding Model.NotifierInterface}" >

将其粘贴到ViewModel中,然后更改值,就可以开始了。只需调用ShowStandartBallon();你在代码隐藏中没有代码

[编辑]

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);
    }

只需在视图中使用绑定到虚拟机中实例化的TaskbarIcon对象的ContentControl。然后直接向VM中的对象发出命令

XAML:


您是如何从viewmodel中初始化它的?我正在努力解决这个问题。通过让viewmodel了解视图,这不是违反了MVVM模式吗?似乎没有任何方法可以使用此方法在XAML中定义图标,然后绑定到触发新气球的属性。如果视图的代码隐藏具有对视图模型的引用,您不能在视图的代码隐藏中公开订阅的视图模型上的事件吗?
<Utility:TaskbarIconRx Visibility= IconSource="/Resources/TinyLogo.ico" BalloonTipNotifier="{Binding Model.NotifierInterface}" >
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);
        }
     }
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);
    }
     <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);
    }