从另一个类和单独的线程更改 WPF 主窗口标签
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15425495/
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
Change WPF mainwindow label from another class and separate thread
提问by iJay
Im working on a WPF application. I have a label called "Status_label" in MainWindow.xaml. and I want to change its content from a different class (signIn.cs).
Normally I'm able to do this
我正在开发 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";
But my problem is,when I'm trying to access it via different thread in signIn.cs class, it gives an error:
但我的问题是,当我尝试通过 signIn.cs 类中的不同线程访问它时,它给出了一个错误:
The calling thread cannot access this object because a different thread owns it.
Can I solve this by using Dispatcher.Invoke(new Action(() =>{..........or something else?
我可以通过使用Dispatcher.Invoke(new Action(() =>{..........或其他方式解决这个问题吗?
EDIT:I'm gonna call this label change action from different class as-well-as separate thread
编辑:我将从不同的类以及单独的线程中调用此标签更改操作
MainWindow.xaml
主窗口.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"));
}
line var mainWin return errorThe calling thread cannot access this object because a different thread owns it.
行 var mainWin 返回错误The calling thread cannot access this object because a different thread owns it.
Please guide me,
请指导我,
Thank you
谢谢
回答by iJay
I resolved my question, hope somebody will need this. But don't know whether this is the optimized way.
我解决了我的问题,希望有人需要这个。但不知道这是否是优化的方式。
In my mainWindow.xaml.cs:
在我的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.csclass
来自我的SignIn.cs课程
MainWindow.main.Status = "Irantha has signed in successfully";
This works fine for me. You can find more details from here, Change WPF window label content from another class and separate thread
这对我来说很好用。您可以从这里找到更多详细信息,从另一个类和单独的线程更改 WPF 窗口标签内容
cheers!!
干杯!!
回答by David
try below snippet:
试试下面的片段:
status_lable.Dispatcher.Invoke(...)
回答by Kasper Halvas Jensen
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 eventhandler in another class that runs in a different thred:
然后在我的事件处理程序中,在另一个以不同线程运行的类中:
internal static void pipeServer_MessageReceived(object sender, MessageReceivedEventArgs e)
{
MainWindow.main.Dispatcher.Invoke(new Action(delegate()
{
MainWindow.main.WindowState = WindowState.Normal;
}));
}
This to show the minimized window when i message is received via a namedPipeline.
当我通过 namedPipeline 接收到消息时,这将显示最小化的窗口。
回答by Dave Smash
Thank you! I wound up with a slightly different solution, but you definitely pointed me in the right direction with your answer.
谢谢!我最终得到了一个略有不同的解决方案,但您的回答绝对为我指明了正确的方向。
For my application, I have a lot of controls in main, and most of the method calls on main were occurring from within the scope of main, so it was simpler to use the default { get; set } within MainWindow.xaml.cs (or to just define the controls in XAML).
对于我的应用程序,我在 main 中有很多控件,并且 main 上的大部分方法调用都发生在 main 的范围内,因此使用默认的 { get; 在 MainWindow.xaml.cs 中设置 }(或仅在 XAML 中定义控件)。
In my parent window's code-behind, I launch the MainWindow in a separate thread like this (simplified example). The key is to define main globally, even though it is instantiated inside of Window_Loaded():
在父窗口的代码隐藏中,我在这样的单独线程中启动 MainWindow(简化示例)。关键是全局定义 main,即使它是在 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-behind, I just interact with the controls as though it is a simple single-threaded application (there is no control of the parent thread from the child thread in my case). I can, however, control main from the parent thread like this:
然后在我的 MainWindow 代码隐藏中,我只是与控件交互,就好像它是一个简单的单线程应用程序一样(在我的情况下,子线程没有对父线程的控制)。但是,我可以像这样从父线程控制 main:
private void button_Click(object sender, RoutedEventArgs e)
{
main.Dispatcher.Invoke(new Action(delegate ()
{
main.myControl.myMethod();
}));
}
By doing it this way, I avoid the complexity of defining everything in code-behind and using the dispatcher from within the code-behind of MainWindow.xaml.cs. There are only a few spots in my application where I modify main from the parent window, so this was simpler for me, but your approach seems equally valid. Thanks again!
通过这样做,我避免了在代码隐藏中定义所有内容以及在 MainWindow.xaml.cs 的代码隐藏中使用调度程序的复杂性。我的应用程序中只有少数几个地方是我从父窗口修改 main 的,所以这对我来说更简单,但你的方法似乎同样有效。再次感谢!
回答by Marco Concas
Simple trick without use Dispatcher.Invoke: In your Windowclass put this:
不使用的简单技巧Dispatcher.Invoke:在你的Window课堂上放这个:
public partial class MyWindow: Window
{
public static MyWindow mywin;
[...]
public MyWindow()
{
InitializeComponent();
mywin = this;
[...]
}
[...]
}
Next in your second class to call the properties you need to add your window name + the label that you've assigned. This is an example:
接下来在您的第二个类中调用您需要添加窗口名称+您分配的标签的属性。这是一个例子:
internal class MySecondClass
{
internal void ChangeAValue()
{
MyWindow.mywin.ATextBox.Text = "Some text"; // I'm changing for example the text for a textbox in MyWindow.
}
}

