问题
一开始使用WPF界面的时候,会有这样的需求就是在后台更新控件,以完成列表更新,计时器,进度条等功能,但WPF这边架构限制,决定子线程是不安全的,如果创建子线程直接操作控件就会出错。
解决
首先可以说明,这里只要使用Dispatcher类来操作就可以了,使用Involke函数,后者提供一个简单的匿名方法,用于委托主线程更新控件。
例子
我建立有一个类,这一个类中有两个函数,一个是RegistTextbox()用于在调用类时候,将主界面的空间传给它,另一个是AddMessageToTextbox()用于将字符串添加到文本框控件,他们的实现很简单
public void RegistTextbox(TextBox tb)
{
MsgTextbox = tb;
}
public void AddMessageToTextbox(string str)
{
Dispatcher.CurrentDispatcher.Invoke(new Action(delegate
{
MsgTextbox.Text += str + "\r\n";
}));
}
这样就可以实现在子线程中控制控件的功能。
要访问其他WPF表单中的控件,您必须将该控件声明为公共控件。WPF中控件的默认声明是公共的,但是您可以使用以下代码指定它:
< TextBox x:Name = " textBox1" x:FieldModifier =" public" />
之后,您可以在应用程序的所有活动窗口中搜索以找到具有此类控制功能的窗口:
foreach(Application.Current.Windows中的窗口)
{
if(window.GetType ()== typeof(Window1))
{
(窗口为Window1).textBox1.Text ="我从另一个窗口更改了它";
}
}
实例:C#通过事件跨类调用WPF主窗口中的控件
xaml.cs文件:
using System;
using System.Timers;
using System.Windows;
using System.Windows.Forms;
namespace ControlUsed
{
//要修改控件的属性 只能在定义控件的xaml或者xaml对应的cs文件修改。首先订阅Monitor的PartEvent事件,当触发PartEvent事件时(可能并不在类MainWindow对象中),被注册的函数就行做出相应的响应。
public partial class MainWindow
{
public MainWindow()
{
Monitor.PartEvent += OnStep;//将该类中的函数注册到Monitor静态类的PartEvent事件中。
}
public void OnStep(Object sender,MessageArgs message)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
MyTextBlock.Text = message.Txtmessage;//设置对应xaml中控件的属性
}));
}
}
}
MessageArgs类:
public class MessageArgs:EventArgs
{
public MessageArgs(string message)
{
this.TxtMessage = message;
}
public string TxtMessage { get; set; }
}
Monitor静态类:
public static class Monitor
{
public static event EventHandler<MessageArgs> PartEvent;//定义在Monitor中的一个事件,参数是MessageArgs对象
public static void InFunction(string message)
{
var messageArg = new MessageArgs
{
TxtMessage=message
};
if (PartEvent != null)//如果mainwindow构造函数中给PartEvent注册了函数就不为null
{
PartEvent(null, messageArg);//触发事件,执行所有注册过的函数
}
}
public static bool MonitorCenter(string s)
{
InFunction(s);//在外部类中修改TextBlock的Text
}
}