- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道通常不应该从 UI 线程以外的线程触摸 UI 元素,但我是 WPF 的新手,我想知道是否可以改进我当前的工作实现。
我有一个仅由通知托盘图标组成的应用程序,我想从后台线程更新该图标。
这是我的 Program.cs 入口点:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (IconHandler notify = new IconHandler())
{
notify.Display();
Application.Run();
}
}
}
class IconHandler : IDisposable
{
NotifyIcon ni;
public IconHandler()
{
ni = new NotifyIcon();
}
public void Display()
{
ni.MouseClick += new MouseEventHandler(ni_MouseClick);
ni.Icon = Resources.icon1;
ni.Visible = true;
new Thread(new ThreadStart(UpdateIcon)).Start();
}
public void UpdateIcon()
{
while (true)
{
// reference ni directly, it updates fine
}
}
public void Dispose()
{
ni.Dispose();
}
void ni_MouseClick(object sender, MouseEventArgs e)
{
// something useful
}
}
最佳答案
Is there anything blatantly incorrect about this? It seems a bit fishy to me - it was just my first attempt. It seems to work for what I want to do, does anyone have any suggestions for a better implementation? Will I run into lifecycle issues with this setup?
NotifyIcon
开始不是 WPF 控件,而是来自 Windows 窗体命名空间。因此,它具有正常的 C# 属性(例如
Icon
、
Visible
),这意味着您可以在非 UI 线程中更改图标属性,而不会引发异常。如果您使用了 WPF 控件,则它们具有依赖属性,并且在 UI 线程之外直接操作依赖属性将导致引发异常。
Will I run into lifecycle issues with this setup?
UpdateIcon
方法扩展为比您当前做的更多并访问这些 WPF 对象,然后是的,您将需要一种策略来处理来自非 UI 线程的更新。
BeginInvoke
在这里,后台线程可以在 UI 线程实际调用该方法之前继续。如果要阻止后台线程,请使用
Invoke
反而。
public void UpdateLabel(Label control, string text)
{
if (Application.Current.Dispatcher.CheckAccess())
control.Content = text;
else
Application.Current.Dispatcher.BeginInvoke(new System.Action(() => UpdateLabel(control, text)), DispatcherPriority.Normal);
}
Events
在后台线程上引发以编程方式更新 WPF 控件,然后您可以隐藏一些跨线程调用作为引发事件的一部分,从而使 WPF 更新例程非常干净且易于阅读。
public void OnRaiseEvent(EventHandler handler, EventArgs args)
{
if (handler != null)
{
if (Application.Current.Dispatcher.CheckAccess())
handler(sender, new PropertyChangedEventArgs(propName));
else
Application.Current.Dispatcher.BeginInvoke(new System.Action(() => handler(sender, args)), DispatcherPriority.Normal);
}
}
XAML
数据绑定(bind)到
MyProperty
MyDataClass
实例的属性类并且该类实现了 INotifyPropertyChanged 接口(interface),您可以将跨线程代码放在数据类中,从而可以从任何线程更新数据。这是该类(class)的示例:-
public class MyDataClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _myProperty;
public string MyProperty { get { return _myProperty;} set { PropertyChanged.SetValueAndNotify(this, ref _myProperty, value); } }
}
SetValueAndNotify
PropertyChanged
上的扩展方法事件。正是在这里我们隐藏了跨线程代码以简化代码的其他部分。这是此扩展方法的定义。
public static class PropertyChangedExtension
{
public static void SetValueAndNotify<T>(this PropertyChangedEventHandler handler, object sender, ref T destination, T source, [CallerMemberName] string propName = "notset")
{
// Is the new value different from the previous value? If there is no difference then there is nothing more to do
if (Equals(destination, source))
return;
// If we got to this point then the new value is different from the old value, so lets make the assignemnt and raise the property changed event
destination = source;
if (handler != null)
{
if (Application.Current.Dispatcher.CheckAccess())
handler(sender, new PropertyChangedEventArgs(propName));
else
Application.Current.Dispatcher.BeginInvoke(new System.Action(() => handler(sender, new PropertyChangedEventArgs(propName))), DispatcherPriority.Normal);
}
}
}
[CallerMemberName]
C#5 中的属性以消除在为 INotifyPropertyChanged 参数提供属性名称时出现的任何键入错误。如果您没有使用最新的,那么您将需要修改 getter 和 setter,如下所示:-
public string MyProperty { get { return _myProperty;} set { PropertyChanged.SetValueAndNotify(this, ref _myProperty, value, "MyProperty"); } }
关于来自后台线程的 WPF NotifyIcon,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31569361/
我知道通常不应该从 UI 线程以外的线程触摸 UI 元素,但我是 WPF 的新手,我想知道是否可以改进我当前的工作实现。 我有一个仅由通知托盘图标组成的应用程序,我想从后台线程更新该图标。 这是我的
所以我正在使用 Visual Studio 2012 并拥有创建 notifyIcon 并显示它的应用程序,如果我关闭应用程序然后 notifyIcon 隐藏,但如果我停止调试器然后仅关闭表单,但 n
我找不到有关系统托盘图标的任何信息,以及它们应该采用什么尺寸才能获得最佳质量。我应该使用不止一种尺寸(16x16、32x32、64x64)吗? 我目前使用 16x16 .ICO 图标,它们看起来很困惑
我想看到一个小通知图标,以表明我编写的脚本仍然处于事件状态(脚本和显示图标都有效)。但我需要图标的上下文菜单中的一个按钮来立即停止脚本。这就是我的问题所在: $objNotifyIcon = New-
所以我正在使用 Visual Studio 2012 并拥有创建 notifyIcon 并显示它的应用程序,如果我关闭应用程序然后 notifyIcon 隐藏,但如果我停止调试器然后仅关闭表单,但 n
我有一个表单 (Form1),上面有一个 NotifyIcon。我有另一种形式 (Form2),我想从中更改 NotifyIcon 的图标。每当我使用此代码时,系统托盘中都会显示一个额外的图标,而不是
当应用程序突然终止时,是否可以从通知区域(系统托盘)中删除 NotifyIcon? 如果没有,如何在应用下次运行时将其删除? 最佳答案 突然?不。您的程序已不复存在,因此没有机会运行任何代码来告诉 s
class MainProgram { static NotifyIcon _notifyIcon; public static void Main() { _
我是新来的,刚开始遇到一个非常神秘的问题。我是英国的一名软件开发人员,拥有超过 15 年的经验,但只在 .Net 中开发了 18 个月。我的 NotifyIcon 鼠标事件没有触发! 我正在使用 C#
在我的 c#(2.0 框架)应用程序中,我使用通知图标控件。我想从这个控件中显示一个气球提示。但是我将“showBalloonTip”事件限制为超时,我想永远显示这个气球。我尝试使用一个计时器来一次又
我在做一些我认为很容易的事情时遇到了麻烦......我无法让我的 NotifyIcon 显示气球提示。基本代码是: public void ShowSystrayBubble(string msg,
我正在使用来自 CodeProject 的 WPF NotifyIcon .它工作正常,但我注意到,在使用 .NET 4.0 进行编译时,ContextMenu 始终位于任务栏上方,对于 .NET 3
_notifyIcon = new NotifyIcon(); _notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingA
我目前正在开发一个 Office 插件,我需要显示一个显示进度的通知对话框,我正在使用 Philipp Sumi's wpf-notifyicon . 我需要显示 notifyicon来自一个单独的线
在 C# 或 Vb.Net 中,使用托管或非托管代码,如何检索 NotifyIcon 的所有者 Form? 我已经检查了 NotifyIcon 类的基本类型以及 ComponentConverter
我目前正在编写一个具有 NotifyIcon 的应用程序,并且我正在尝试找出一种在其上叠加文本的方法。因此,例如,如果图标指示打开的文件数,则它会在图标上方加上数字。 有办法吗?我已经看到 Notif
我正在使用 NotifyIcon 类在任务栏中显示一个图标。该图标执行 2 个功能 - 当用户单击左键时它应该显示一个窗口,当用户单击右键时它应该显示上下文菜单。除了在用户单击上下文菜单中的选项后显示
我在测试我的 notifyIcon 使用的是哪个图标时遇到问题。 我有一个为我的程序实例化的通知图标。当程序运行时,我在我的代码中为它分配了一个图标。 public Form1() {
我目前正在使用(很棒的)第三方 WPF NotifyIcon 我像这样创建了一个托盘弹出窗口:
我正在创建一个只有系统托盘的应用程序。没有主窗体的图标有点复杂,但通过 StackOverflow 上的先前主题我已经解决了。右键单击效果很好,我已经在上下文菜单中链接,等等。 我在左键单击时遇到问题
我是一名优秀的程序员,十分优秀!