从另一个类和独立的线程更改WPF主窗口标签(Change WPF mainwindow label

2019-08-17 15:20发布

进出口工作在WPF应用程序。 我有一个名为“Status_label”的标签MainWindow.xaml 。 我想改变从一个不同的类(signIn.cs)的内容。 通常情况下,我能做到这一点

var mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is MainWindow) as MainWindow;
mainWin.status_lable.Content = "Irantha signed in";

但我的问题是,当我试图通过在signIn.cs类不同的线程访问它,它给出了一个错误:

The calling thread cannot access this object because a different thread owns it.

我可以通过解决这个Dispatcher.Invoke(new Action(() =>{..........还是其他什么东西?

编辑:我要打电话从不同的类此标签的变化行动,精心为单独的线程

MainWindow.xaml

<Label HorizontalAlignment="Left" Margin="14,312,0,0" Name="status_lable" Width="361"/>

SignIn.cs

    internal void getStudentAttendence()
    {
        Thread captureFingerPrints = new Thread(startCapturing);
        captureFingerPrints.Start();
    }

void mySeparateThreadMethod()
{
    var mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is MainWindow) as MainWindow;
    mainWin.status_lable.Dispatcher.Invoke(new Action(()=> mainWin.status_lable.Content ="Irantha signed in"));
}

线VAR孟文返回错误The calling thread cannot access this object because a different thread owns it.

请指导我,

谢谢

Answer 1:

我解决了我的问题,希望有人会需要这个。 但不知道这是否是最优化的方式。

在我mainWindow.xaml.cs:

    public  MainWindow()
    {
      main = this;
    }

    internal static MainWindow main;
    internal string Status
    {
        get { return status_lable.Content.ToString(); }
        set { Dispatcher.Invoke(new Action(() => { status_lable.Content = value; })); }
    }

从我SignIn.cs

 MainWindow.main.Status = "Irantha has signed in successfully";

这对我来说工作得很好。 你可以从这里找到更多的细节, 从另一个阶级和独立的线程更改WPF窗口标签内容

干杯!!



Answer 2:

试试下面的代码片段:

status_lable.Dispatcher.Invoke(...)


Answer 3:

多亏了答案,他们使我在正确的方向。 我结束了这个简单的解决方案:

public partial class MainWindow : Window
{
    public static MainWindow main;

    public MainWindow()
    {
        InitializeComponent();                        
        main = this;
    }
}

然后我在不同thred运行另一个类的事件处理程序:

internal static void pipeServer_MessageReceived(object sender, MessageReceivedEventArgs e)
    {
        MainWindow.main.Dispatcher.Invoke(new Action(delegate()
        {
            MainWindow.main.WindowState = WindowState.Normal;
        }));
    }

当经由namedPipeline接收我此消息以显示最小化窗口。



Answer 4:

谢谢! 我结束了一个稍微不同的解决方案,但你绝对指着我与你的答案正确的方向。

对于我的申请,我有很多的控制主,大多数方法的调用主要是从主要范围内发生的,所以这是简单的使用默认的{获得; 设定}内MainWindow.xaml.cs(或只在定义的XAML对照)。

在我的父窗口的代码隐藏,我启动主窗口中像这样(简化的例子)一个单独的线程。 关键是要确定主要全球范围内,即使它被实例化内部Window_Loaded()的:

    public ParentWindow()
    {
        InitializeComponent();
    }

    MainWindow main;

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Thread otherThread = new Thread(() =>
        {
            main = new MainWindow();
            main.Show();

            main.Closed += (sender2, e2) =>
                main.Dispatcher.InvokeShutdown();

            System.Windows.Threading.Dispatcher.Run();
        });

        otherThread.SetApartmentState(ApartmentState.STA);
        otherThread.Start();

    }

然后在我的主窗口代码隐藏,我刚刚与控件进行交互,就好像它是一个简单的单线程应用程序(也就是在我的情况下,不从子线程父线程的控制)。 我可以,但是,控制从这样父线程主:

private void button_Click(object sender, RoutedEventArgs e)
        {
            main.Dispatcher.Invoke(new Action(delegate () 
                {
                    main.myControl.myMethod(); 
                }));

        }

通过做这种方式,我避免了定义一切代码隐藏和使用调度从MainWindow.xaml.cs的代码隐藏中的复杂性。 只有在我的应用程序的几个景点,我修改了父窗口的主,所以这是简单的我,但你的做法似乎同样有效。 再次感谢!



文章来源: Change WPF mainwindow label from another class and separate thread