C# WPF - 如何简单地从另一个类/线程更新 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33680398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:32:02  来源:igfitidea点击:

C# WPF - How to simply update UI from another class/thread

c#wpfmultithreadinguser-interface

提问by Jakub Lok?a

I couldn't find a simplesolution to this problem. That's why I'm asking.

我找不到解决这个问题的简单方法。这就是为什么我要问。

I have a WPF windowlike this:

我有一个像这样的 WPF窗口

<Window x:Class="WPF_Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="640" Height="480">

    <Button Name="xaml_button" Content="A Text."/>
</Window>

And a MainWindow class:

和一个 MainWindow

using System.Windows;
using System.Threading;

namespace WPF_Test
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            xaml_button.Content = "Text changed on start.";
        }
    }

    private void xaml_button_Click()
    {
        Threading.t1.Start();
        UIControl.ChangeButtonName("Updated from another CLASS.");
    }
}

The button's Contentproperty successfullychanged itself. But what I want to do, is to change the property in anotherclass orthread. What I tried is this:

按钮的Content属性成功地改变了自己。但是我想做的是更改另一个线程中的属性。我试过的是这样的:

class UIControl
{
    public static void ChangeButtonName(string text)
    {
        var window = new MainWindow();
        window.xaml_button.Content = text;
    }
}

It obviously doesn't work, because the public MainWindow()changes the Contentproperty back to the original one, and brings some issues along with it.

它显然不起作用,因为将属性public MainWindow()更改Content回原始属性,并随之带来一些问题。

Also I want to use this while multithreading. My simple threading class looks like this:

我也想在多线程时使用它。我的简单线程类如下所示:

class Threading
{
    public static Thread t1 = new Thread(t1_data);

    static void t1_data()
    {
        Thread.Sleep(2000);
        UIControl.ChangeButtonName("Updated from another THREAD.");
    }
}

回答by Jakub Lok?a

To do this, I'd recommend declaring a staticvariable that holds a UI control of your likings, in this case, a Button. Also add using System.Windows.Controls;at the beginning. So your code should look like this:

为此,我建议声明一个静态变量,该变量包含您喜欢的 UI 控件,在本例中为Button. 也在using System.Windows.Controls;开头添加。所以你的代码应该是这样的:

using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace WPF_Test
{
    public partial class MainWindow : Window
    {
        public static Button xamlStaticButton;

        public MainWindow()
        {
            InitializeComponent();
            xamlStaticButton = xaml_button;
            xamlStaticButton.Content = "Text changed on start";
        }

        private void xaml_button_Click(object sender, RoutedEventArgs e)
        {
            Threading.t1.Start();
            UIControl.ChangeButtonName("Updated from another CLASS.");
        }
    }
}

So pretty much what I did was to make a placeholderfor the button, then assigningit on start.

所以我所做的几乎就是为按钮制作一个占位符,然后在开始时分配它。

class UIControl : MainWindow
{
    public static void ChangeButtonName(string text)
    {
        App.Current.Dispatcher.Invoke(delegate {
            xamlStaticButton.Content = text;
        });
    }
}

Now I inheritedthe MainWindowclass to the UIControlclass for the sake of convenience. Also to make this work with multithreading, I added the App.Current.Dispatcher.Invoke(delegate { /*your UI code you want to execute*/});. This will make sureyour UI will update even if you are on another thread.

现在,我继承MainWindow类的UIControl类为方便起见。同样为了使这项工作与多线程一起工作,我添加了App.Current.Dispatcher.Invoke(delegate { /*your UI code you want to execute*/});. 这将确保即使您在另一个线程上,您的 UI 也会更新。