Change WPF shortcut mainwindow from another class and a separate thread

Im working on a WPF application. I have a label "Status_label" in MainWindow.xaml . and I want to change its contents from another class (signIn.cs). I can usually do this

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

But my problem is that when I try to access it through another thread in the signIn.cs class, it gives an error:

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

Is it possible to solve this using Dispatcher.Invoke(new Action(() =>{.......... or something else?

EDIT: I'm going to call this shortcut change action from another class the same as a separate thread

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")); } 

string var mainWin return error The calling thread cannot access this object because a different thread owns it.

I ask you to,

thanks

+7
source share
4 answers

I solved my question, I hope someone will need it. But I don’t know if this is an optimized way.

In my 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; })); } } 

from my SignIn.cs class

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

This works great for me. You can find more details from here. Change the contents of WPF shortcuts from another class and a separate thread

Hooray!!

+22
source

try below snippet:

 status_lable.Dispatcher.Invoke(...) 
+2
source

Thanks to the answers, they led me in the right direction. I ended up with this simple solution:

 public partial class MainWindow : Window { public static MainWindow main; public MainWindow() { InitializeComponent(); main = this; } } 

Then in my event handler in another class that works in another file:

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

This is to show a minimized window when the message I received through namedPipeline.

+2
source

Thanks! I ended up with a slightly different solution, but you definitely pointed me in the right direction with your answer.

For my application, I have many controls mostly, and most calls to the main method come from the main scope, so it was easier to use the default value {get; set} inside MainWindow.xaml.cs (or just define controls in XAML).

In my parent window, behind the code, I run MainWindow in a separate thread like this (simplified example). The key must be defined globally globally, even if it is created inside 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(); } 

Then, in my MainWindow code, I just interact with the controls as if it were a simple single-threaded application (in my case there is no control over the parent thread from the child thread). However, I can control main from the parent thread as follows:

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

This way I avoid the complexity of defining everything in encoding and using the dispatcher from within the MainWindow.xaml.cs code. There are only a few points in my application where I change main from the parent window, so it was easier for me, but your approach seems the same. Thanks again!

+1
source

All Articles