Reputation: 959
I have a WPF UI , On click of a button I am starting threads . I want to read few txtbox values on the UI from the thread and want to update a textbox on the UI with the status of the thread
I am trying to pass the handle of the UI to the thread and get the window back from the handle ( as we do in MFC) and updat the UI.
I am able to get the handle as " IntPtr ParentHandle = new WindowInteropHelper(this).Handle;"
But dont know how to get the window from the handle .
OR
Is there anyother way i can update and retreive values on WPF UI from a thread .
Upvotes: 0
Views: 3499
Reputation: 91
For anybody (like me) comming here in the actual intent of retrieving a Window
from a window handle (HWND)
You can only get Window
instances of windows of your current process. You can't get a Window
instance for a window of a foreign process.
Create a new WindoCollectionExtensions.cs
and paste this extensions method:
using System.Windows;
using System.Windows.Interop;
namespace My.Code;
public static class WindowCollectionExtensions
{
public static Window GetWindow(this WindowCollection list, int hwnd)
{
foreach(Window wnd in list)
{
if (new WindowInteropHelper(wnd).Handle == hwnd)
{
return wnd;
}
}
return null;
}
With this in place you can easily get the Window
like this:
Window window = System.Windows.Application.Current.Windows.GetWindow(hwnd);
Upvotes: 0
Reputation: 56697
No need to use any handles. Just pass object references. You can create the thread using the ParameterizedThreadStart
class, which takes an object
parameter. So you can define an object that contains members for all the values you want to pass to the thread, instead of having the thread retrieve them from the UI. Also, you can pass a reference to your window class, so when the thread is done (or to update the status), you can just use that reference (remember to use the Dispatcher to update the controls (in WinForms you'd have done this.Invoke
).
This could look like the following:
public class WPFWindow ...
{
private class ThreadData
{
public int Value1;
public string Value2;
public WPFWindow Window;
}
....
private void StartThread()
{
ThreadData tdata = new ThreadData();
tdata.Value1 = 42;
tdata.Value2 = "Hello World!";
tdata.Window = this;
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
t.Start(tdata);
}
private void ThreadMethod(object data)
{
ThreadData tdata = (ThreadData)data;
// ... process values here
// Update controls
if(tdata.Window.textbox.Dispatcher.CheckAccess())
{
// The calling thread owns the dispatcher, and hence the UI element
tdata.Window.textbox.AppendText(...);
}
else
{
// Invokation required
tdata.Window.textbox.Dispatcher.Invoke(DispatcherPriority.Normal, delegate);
}
}
}
Please note that I'm writing this blindly without having testet this in WPF. This is, however, the way I do it all the time in WinForms.
Upvotes: 1