C# 按第二类更改文本
我现在正在努力学习c# 我的问题是: 我有两门课C# 按第二类更改文本,c#,wpf,code-behind,C#,Wpf,Code Behind,我现在正在努力学习c# 我的问题是: 我有两门课MainWindow.xaml.cs用于UI,另一个名为dosomething.cs 如果单击UI上的按钮,则应调用dosomething.cs中的方法。那很好用。我希望dosomething.cs在运行单击处理程序时(需要一些时间)将实际状态告知UI status_textblock = "test"; for (int i = 1; i<1000000; i++) i += i; Thread.sleep(100); Status_tex
MainWindow.xaml.cs
用于UI,另一个名为dosomething.cs
如果单击UI上的按钮,则应调用dosomething.cs
中的方法。那很好用。我希望dosomething.cs
在运行单击处理程序时(需要一些时间)将实际状态告知UI
status_textblock = "test";
for (int i = 1; i<1000000; i++)
i += i;
Thread.sleep(100);
Status_textblock = i.tostring();
}
status\u textblock=“测试”;
对于(int i=1;i我将在此处使用BackgroundWorker
。在dosomething.cs
中的函数中启动worker,您的UI CodeBehind订阅dosomething事件
小例子:
UI代码隐藏:
private void ButtonClick(object sender, ...)
{
var doSomething = new DoSomething();
doSomething.StatusChanged += OnStatusChanged;
doSomething.Do();
}
private void OnStatusChagned(string state)
{
// Update the UI with the state
}
DoSomething
public class DoSomething
{
public void Do()
{
var worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += WorkerOnDoWork;
worker.ProgressChanged += WorkerOnProgressChanged;
worker.RunWorkerAsync("Paremeter to pass to the BackgroundWorker");
}
private void WorkerOnProgressChanged(object sender, ProgressChangedEventArgs e)
{
var temp = StatusChanged;
if (temp != null)
temp((string) e.UserState);
}
private void WorkerOnDoWork(object sender, DoWorkEventArgs e)
{
var worker = (BackgroundWorker) sender;
// If you want to get the passed argument you can call
var parameter = e.Argument;
for (int i = 0; i < 100000; i++)
{
// do your background-stuff here
// ...
// Notify the UI
worker.ReportProgress(0, "STATUS-OBJECT");
}
}
public delegate void OnStatusChanged(string status);
public event OnStatusChanged StatusChanged;
}
公共类DoSomething
{
公营部门
{
var worker=新的BackgroundWorker();
worker.WorkerReportsProgress=true;
worker.DoWork+=workerdowork;
worker.ProgressChanged+=workerProgressChanged;
worker.RunWorkerAsync(“传递给后台工作人员的参数”);
}
私有void workerProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
var temp=状态已更改;
如果(温度!=null)
temp((字符串)例如UserState);
}
私有void workerDoWork(对象发送方,DoWorkerVentargs e)
{
var worker=(BackgroundWorker)发送方;
//如果您想获得已传递的参数,可以调用
var参数=e.参数;
对于(int i=0;i<100000;i++)
{
//在这里做你的背景资料
// ...
//通知用户界面
worker.ReportProgress(0,“状态对象”);
}
}
公共委托void OnStatusChanged(字符串状态);
公共事件状态更改状态更改;
}
问题1:对主窗口的引用。cs:
private void ButtonClick(object sender, ...)
{
var doSomething = new DoSomething();
doSomething.StatusChanged += OnStatusChanged;
doSomething.Do();
}
private void OnStatusChagned(string state)
{
// Update the UI with the state
}
在面向对象编程中,为了更好地概述、可测试性继承等,您将组件解耦。但您必须考虑如何在对象之间传播引用。我的意思是:类dosomething的实例必须具有对主窗口的引用,才能更新其上的任何内容。
您现在要做的是:在方法中创建一个新的MainWindow实例并更改状态(但不是实际上可视化的MainWindow的状态)
您可以将对实际MainWindow的引用传递给函数。这称为依赖项注入。通常,您只会注入由MainWindow类实现的接口,因此其他类也可以使用此功能,但这太过分了。
快速修复:
public void Do(MainWindow window)
{
window.status_textblock = "test";
for (int i = 1; i<1000000; i++)
i += i;
Thread.sleep(100);
window.status_textblock = i.tostring();
}
但是这仍然不起作用,因为线程被阻塞(使用Thread.Sleep),并且只有在线程可以自由渲染可视化时,才会在最后可视化结果
问题2:您必须在另一个线程/任务中运行它
public void Do(MainWindow window)
{
Task.Factory.StartNew(() => {
window.status_textblock = "test";
for (int i = 1; i < 1000000; i++)
i += i;
Thread.sleep(100);
window.status_textblock = i.tostring();
});
}
public void Do(主窗口)
{
Task.Factory.StartNew(()=>{
window.status_textblock=“测试”;
对于(int i=1;i<1000000;i++)
i+=i;
睡眠(100);
window.status_textblock=i.tostring();
});
}
但是等等,这也不行,因为您试图从另一个线程更新UI,这是不允许的
问题3:使用STA线程更新UI
在MainWindow类中,您创建了一个更新STA线程上状态文本的方法(STA线程是唯一允许更新UI上任何内容的方法)
public void UpdateStatus(字符串状态)
{
if(this.Dispatcher.CheckAccess())
this.status_textblock=状态;
其他的
this.Dispatcher.Invoke(新操作(UpdateStatus),状态);
}
从DoSomething类调用UpdateStatus方法:
public void Do(MainWindow window)
{
Task.Factory.StartNew(() => {
window.UpdateStatus("test");
for (int i = 1; i < 1000000; i++)
i += i;
Thread.sleep(100);
window.UpdateStatus(i.tostring());
});
}
public void Do(主窗口)
{
Task.Factory.StartNew(()=>{
窗口更新状态(“测试”);
对于(int i=1;i<1000000;i++)
i+=i;
睡眠(100);
UpdateStatus(i.tostring());
});
}
-->这很有效!在更多关于此主题的帖子中建议使用Backgroundworker。您要做的是:
单击按钮时,启动一个新的Backgroundworker
绑定到以下事件:DoWork
和ProgressChanged
在DoWork委托中,您可以使用自定义对象或单个整数调用ReportProgress
绑定到ProgressChanged
的方法将在UI线程上启动,您可以在那里更新标签或任何您喜欢的内容
也许你应该用中的答案“刷新”页面/视图
有关Backgroundworker的更多信息
使用谷歌翻译。你到底有什么问题?我想你不知道dosomthing类上下文中的main类是否正确?让我们不要急于下结论,让作者用正确的英语回答问题。我已经翻译了这篇文章,现在需要复习。问题是..当我用MainWindow main=new MainWindow()调用MainWinodw时;main.status_textblock.Text=“test”窗户什么也不关
public void Do(MainWindow window)
{
Task.Factory.StartNew(() => {
window.UpdateStatus("test");
for (int i = 1; i < 1000000; i++)
i += i;
Thread.sleep(100);
window.UpdateStatus(i.tostring());
});
}