Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按第二类更改文本_C#_Wpf_Code Behind - Fatal编程技术网

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

我现在正在努力学习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_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());
        });
    }