我想知道如何将NotifyIcon与Caliburn.Micro集成。
我正在尝试使用低级别的Caliburn API进行集成。以下是相关类:
ITrayIconManager
public interface ITrayIconManager
{
ITrayIcon GetOrCreateFor<T>();
}
ITrayIcon 是一个包装器,它封装了WPF NotifyIcon中的TaskbarIcon。
public interface ITrayIcon : IDisposable
{
void ShowBalloonTip(string title, string message, BalloonIcon symbol);
void Show();
void Hide();
}
ISetTrayIconInstance
public interface ISetTrayIconInstance
{
ITrayIcon Icon { set; }
}
TrayIconWrapper
public class TrayIconWrapper : ITrayIcon
{
private readonly TaskbarIcon icon;
public TrayIconWrapper(TaskbarIcon icon)
{
this.icon = icon;
}
public bool IsDisposed { get; private set; }
public void Dispose()
{
icon.Dispose();
IsDisposed = true;
}
public void Show()
{
icon.Visibility = Visibility.Visible;
}
public void Hide()
{
icon.Visibility = Visibility.Collapsed;
}
public void ShowBalloonTip(string title, string message, BalloonIcon symbol)
{
icon.ShowBalloonTip(title, message, symbol);
}
}
TrayIconManager
public class TrayIconManager : ITrayIconManager
{
private readonly IDictionary<WeakReference, WeakReference> icons;
public TrayIconManager()
{
icons = new Dictionary<WeakReference, WeakReference>();
}
public ITrayIcon GetOrCreateFor<T>()
{
if (!icons.Any(i => i.Key.IsAlive && typeof(T).IsAssignableFrom(i.Key.Target.GetType())))
return Create<T>();
var reference = icons.First(i => i.Key.IsAlive && typeof(T).IsAssignableFrom(i.Key.Target.GetType())).Value;
if (!reference.IsAlive)
return Create<T>();
var wrapper = (TrayIconWrapper)reference.Target;
if (wrapper.IsDisposed)
return Create<T>();
return wrapper;
}
private ITrayIcon Create<T>()
{
var rootModel = IoC.Get<T>();
var view = ViewLocator.LocateForModel(rootModel, null, null);
var icon = view is TaskbarIcon ? (TaskbarIcon)view : new TaskbarIcon();
var wrapper = new TrayIconWrapper(icon);
ViewModelBinder.Bind(rootModel, view, null);
SetIconInstance(rootModel, wrapper);
icons.Add(new WeakReference(rootModel), new WeakReference(wrapper));
return wrapper;
}
private void SetIconInstance(object rootModel, ITrayIcon icon)
{
var instance = rootModel as ISetTrayIconInstance;
if (instance != null)
instance.Icon = icon;
}
}
这是代码,现在我该如何使用它?这段代码依赖于Caliburn View-ViewModel绑定,也就是说,我需要为TasbarkIcon创建一个ViewModel和一个View(必须从TaskbarIcon控件继承): TrayIconViewModel
public class TrayIconViewModel : IMainTrayIcon, ISetTrayIconInstance
{
public TrayIconViewModel()
{
}
public ITrayIcon Icon { get; set; }
public void ShowWindow()
{
Icon.Hide();
System.Windows.Application.Current.MainWindow.Show(); //very very bad :(
}
ITrayIcon是TaskbarIcon控件的包装器。现在我可以从我的ViewModel中调用它的方法,这非常棒。
TrayIconView(cal:Message:Attach不起作用-ShowWindow永远不会被触发)
<tb:TaskbarIcon x:Class="Communicator.Softphone.Views.TrayIconView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:tb="http://www.hardcodet.net/taskbar"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
IconSource="/Communicator.ControlLibrary;component/Assets/phone_icon.ico"
ToolTipText="Secretária do Futuro - Comunicador"
Visibility="Collapsed"
cal:Message.Attach="[Event TrayLeftMouseDown] = [Action ShowWindow()]">
关于我的ShellViewModel(trayIcon是TaskbarIcon的包装器):
private ITrayIcon trayIcon;
protected override void OnActivate()
{
trayIcon = trayIconManager.GetOrCreateFor<IMainTrayIcon>();
ActivateItem(containers.FirstOfType<IPhone>());
}
public override void CanClose(Action<bool> callback)
{
trayIcon.Show();
trayIcon.ShowBalloonTip("Comunicador", "Comunicador foi minimizado", BalloonIcon.Info);
(GetView() as Window).Hide();
callback(false);
}
trayIcon.Show()
可以正常工作,但是trayIcon.ShowBallonTip(...)
没有任何反应,没有错误提示。
问题汇总:
- 绑定Message.Attach无效,尽管Caliburn输出日志表明已经生效。
在wrapper上调用ShowBallonTip似乎不起作用,尽管它调用了实际的TaskbarIcon方法。(在未连接调试器的情况下可以正常工作)
System.Windows.Forms
的参考资料,如果有的话,你可以直接在视图模型中初始化NotifyIcon。希望这可能会有所帮助。 - D_LearningSystem.Windows.Forms
的 NotifyIcon。 - JobaDiniztrayIcon.ShowBalloonTip(new AnyViewModel(), PopupAnimation.Slide, TimeSpan.FromSeconds(5));
这真的很好,因为Caliburn将负责实例化AnyViewModel的视图。 - JobaDiniz