我有一个带有标题、标签和确定按钮的警告框。每当它应该弹出时,它应该重新使用同一个窗口,而不是打开一个新窗口。
我从外部线程收到一个对话框事件。它可以接收已知程序之外的消息。Show()
每次收到消息时我都想打电话。
public partial class AlertBox : Form
{
private static AlertBox instance;
public static AlertBox Instance => instance ?? (instance = new AlertBox());
private AlertBox()
{
InitializeComponent();
}
private void AlertBox_Load(object sender, EventArgs e)
{
MessageLabel.Text = "";
Text = "";
}
public void Show(string text, string title)
{
Show();
BringToFront();
Text = title;
MessageLabel.Text = text;
}
private void OkButton_Click(object sender, EventArgs e)
{
MessageLabel.Text = "";
Text = "";
Hide();
}
}
但是,Show(text, title)
如图所示调用时:
internal class Driver
{
private readonly AlertBox _alertBox = AlertBox.Instance;
public void Initialize()
{
// Receive dialog event.
_connection.OnDialogReceived += (text, title) =>
{
_alertBox.Show(text, title);
};
}
}
警报框出现,设置窗口标题,然后冻结。请注意,该按钮已变得不可见。
我曾尝试使用Invoke
. 它冻结,结果完全相同。
public void ShowWithInvoke(string text, string title)
{
if (!Created)
{
CreateControl();
}
if (!IsHandleCreated)
{
CreateHandle();
}
Invoke((MethodInvoker)delegate
{
Show();
BringToFront();
Text = title;
});
if (!MessageLabel.Created || !MessageLabel.IsHandleCreated)
{
MessageLabel.CreateControl();
}
MessageLabel.Invoke((MethodInvoker)delegate
{
MessageLabel.Text = text;
});
}
解决此问题的常用方法是将发送警报的代码与显示警报的代码分离。
首先,您应该创建一个类,该类的唯一目的是将更新传递给正在侦听的任何 UI。
public class MessageUpdater
{
public event EventHandler<string> MessageSent;
public void SendMessage(string message)
{
this.MessageSent?.Invoke(this, message);
}
}
这很简单。它只接受消息,如果有附加到事件的处理程序,它就会引发事件。
现在,您AlertBox
只需接受一个MessageUpdater
实例并在触发事件Label
时更新它MessageSent
。
public partial class AlertBox : Form
{
public AlertBox()
{
InitializeComponent();
}
private MessageUpdater _messageUpdater = null;
public MessageUpdater MessageUpdater
{
set
{
if (_messageUpdater != null)
{
_messageUpdater.MessageSent -= UpdateMessage;
}
if (value != null)
{
_messageUpdater = value;
_messageUpdater.MessageSent += UpdateMessage;
}
}
}
private void UpdateMessage(object sender, string message)
{
if (this.InvokeRequired)
{
this.Invoke((Action)(() => this.UpdateMessage(sender, message)));
}
else
{
this.MessageLabel.Text = message;
}
}
}
这里有两个棘手的部分是处理新的附件MessageUpdater
(以及删除现有的附件),然后在需要时将调用编组到 UI 线程。
我创建的用于测试的代码相当简单。
var mu = new MessageUpdater();
var counter = 0;
var timer = new System.Threading.Timer((System.Threading.TimerCallback)(x =>
{
mu.SendMessage((counter++).ToString());
}), null, TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0));
var ab = new AlertBox();
ab.MessageUpdater = mu;
ab.ShowDialog();
这里棘手的部分是System.Threading.Timer
我曾经MessageUpdater
在非 UI 线程上将消息推送到以便.ShowDialog
不会冻结。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句