WPF:用主窗口生成了一个窗口,怎么在新窗口控制主窗口的textblock显示文字?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF:用主窗口生成了一个窗口,怎么在新窗口控制主窗口的textblock显示文字?相关的知识,希望对你有一定的参考价值。
给新窗口定义事件。
这里由于字数限制,两个窗口我都用同一个类了。
<Window x:Class="WpfApplication1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock x:Name="label" VerticalAlignment="Top" Text="Hello!" Margin="10,99,10,0" />
<TextBox x:Name="txtInput" VerticalAlignment="Center" Text="Hello!" HorizontalAlignment="Left" Height="20" Width="456"/>
<Button Content="点我" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click"/>
<Button Content="修改" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click_1" Margin="0,154,10,0"/>
</Grid>
</Window>using System;
using System.Windows;
namespace WpfApplication1
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
/// <summary>
/// 处理文本变化时间的委托
/// </summary>
public delegate void TextChangedHandler(object sender, TextChangedArgs e);
/// <summary>
/// 用来记录变化的文本
/// </summary>
public class TextChangedArgs : EventArgs
public string Text get; set;
public TextChangedArgs(string text)
Text = text;
/// <summary>
/// 文本变化事件
/// </summary>
public event TextChangedHandler TextChanged;
private void Button_Click(object sender, RoutedEventArgs e)
MainWindow mw = new MainWindow();
mw.TextChanged += Mw_TextChanged;
mw.Show();
/// <summary>
/// 处理TextChanged事件
/// </summary>
private void Mw_TextChanged(object sender, TextChangedArgs e)
this.label.Text = e.Text;
private void Button_Click_1(object sender, RoutedEventArgs e)
if (TextChanged != null)
//引发事件,txtInput.Text 可以改成任意字符串
TextChanged.Invoke(this, new TextChangedArgs(txtInput.Text));
参考技术A 把主窗口的引用传到新窗口里追问
能写个代码吗?就是自己试了不成功才来问别人的T^T
追答主窗口:form1=new form1(this)
子窗口:
class form2
public form2(form1 f)
把f用变量保存起来。想用的时候调用
在新线程错误上创建 WPF 新窗口
【中文标题】在新线程错误上创建 WPF 新窗口【英文标题】:WPF new window creation on new thread error 【发布时间】:2015-08-30 22:49:03 【问题描述】:void itemCommand_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)
var thread = new Thread(() =>
if (LoginCheck())
ItemWindow itw = new ItemWindow();
//Dispatcher.CurrentDispatcher.Invoke((System.Action)(() =>
//
itw.Show();
itw.Closed += (sender2, e2) => itw.Dispatcher.InvokeShutdown(); ;
//));
Dispatcher.Run();
);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
我不断收到错误消息“调用线程无法访问此对象,因为不同的线程拥有它。”在线“itw.show();”当此函数调用两次时。第一次调用它工作正常,在窗口关闭并尝试再次打开后,它失败了。当我注释掉“Invoke”方法时,它也不适用于 Dispatcher。请帮助我找到解决方案。 谢谢。
----------------- 编辑
我创建一个新线程的原因是因为它是一个 Excel 插件。如果我从主线程创建它们,我无法从主线程创建窗口,这是与窗口冲突的 excel。 我不明白的是,为什么新线程中的新实例(ItemWindow)会与旧线程发生冲突。
【问题讨论】:
为什么要创建一个新线程来显示这个窗口?这通常不是一个好主意。其次,我已经尝试过了,效果很好(除了我不知道LoginCheck
做了什么)。异常发生在哪里?
所有与 UI 相关的代码都必须在主线程中运行。您想在这里实现什么目标?
通常,此错误是指您尝试从已串接的表单访问第一个表单上的属性。我们实际上必须看看导致问题的第二种形式发生了什么。
你为什么要创建一个新的调度程序?您是否希望每个窗口都有一个专用的 UI 线程?
LoginCheck()
执行的操作会跨入主线程的边界(可能),或者您在 App.xaml 中定义了您在应用程序范围内使用的资源。一旦像这样生成第二个窗口线程,它就会因这个错误而崩溃,因为它试图拉取 App.xaml 中定义的资源,这些资源属于主线程。
【参考方案1】:
我在一个新应用程序中创建了一个简单的测试方法,当我单击主窗体上的(唯一)按钮时调用该方法。该方法如下所示:
private void Button_Click(object sender, RoutedEventArgs e)
Thread thread = new Thread(() =>
Window1 window = new Window1();
window.Closed += (s, a) => window.Dispatcher.InvokeShutdown();
window.Show();
System.Windows.Threading.Dispatcher.Run();
);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Window1
是我制作的一个窗口类,上面只有一个 TextBlock
。我可以根据需要多次单击该按钮,它会继续打开新窗口而没有问题(无论我是否先关闭前一个窗口)。
我怀疑问题出现在您没有在某处向我们展示的代码中。您需要非常小心,新线程上的任何内容都不会尝试访问与主线程相关的任何 UI。运行在不同线程上的 Windows 不能相互通信,除非它们通过另一个线程的调度程序。当从创建对象的线程以外的线程访问 DispatcherObject 的任何方法或属性时,将引发您看到的异常。
退一步说,为什么新窗口在自己的线程上很重要?除非新窗口要独占线程,否则它可能会在主线程上运行良好。如果您正在运行一些长时间的阻塞操作,那么可能应该将该操作单独移动到一个线程而不是整个窗口。我不知道你到底在做什么,但这是值得考虑的事情。
编辑:意识到您可能不是在典型的 WPF 应用程序中运行(看起来您可能在 Office 插件中),我更新了我的测试以在它们自己的线程上完全独立地启动窗口。但是,我仍然能够连续启动两个窗口而没有问题。
这是我的新测试。这个方法和测试类Window1
是我的应用的全部。
[STAThread]
public static int Main(string[] args)
ThreadStart threadFunc = () =>
Window1 window = new Window1();
window.Closed += (s, a) => window.Dispatcher.InvokeShutdown();
window.Show();
System.Windows.Threading.Dispatcher.Run();
;
Thread thread = new Thread(threadFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
thread = new Thread(threadFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return 0;
因此,您尝试做的事情似乎没有任何内在错误,我也没有在您的代码中看到任何明显的问题。我怀疑在显示自定义窗口时某处发生了一些无效的跨线程通信。 (要么是这样,要么你遇到了特定于 Office 插件的问题。)
【讨论】:
我认为这与 excel 插件有关。我不明白的是,为什么新线程中的新实例(ItemWindow)会与旧线程发生冲突。 查看异常的调用栈了吗?也许它会揭示一些关于是什么导致无效调用的线索。此外,您可以关闭“仅我的代码”调试器选项以在 Visual Studio 的“调用堆栈”窗口中查看完整的调用堆栈(包括来自外部程序集的方法)。【参考方案2】:您正在尝试将事件处理程序连接到 ItemWindow 之后它已经可见。
您需要从以下位置切换订单:
ItemWindow itw = new ItemWindow();
itw.Show();
itw.Closed += (sender2, e2) => itw.Dispatcher.InvokeShutdown(); ;
到
ItemWindow itw = new ItemWindow();
itw.Closed += (sender2, e2) => itw.Dispatcher.InvokeShutdown(); ;
itw.Show();
【讨论】:
【参考方案3】:一个可能的原因是依赖属性。在线程方面,依赖属性有点挑剔。
即使你不定义自己的 DepProps,你的窗口仍然会有一些,而且没有办法摆脱它们。
DepProps 有一个明显的缺点:它们是线程绑定的,不能从另一个线程访问。哪个线程拥有所有权限由初始化 DepProps 的线程定义,在您的情况下是对new ItemWindow()
的第一次调用。在第一次调用之后,您的线程已设置,您需要该线程来访问您的 DepProps。
第一个窗口没有问题,但第二个显然有不同的线程。我不知道 DepProps 是如何做到这一点的,但您可以尝试捕获和恢复第一个线程的同步上下文。另一种选择是捕获第一个线程的调度程序(不是主线程)
【讨论】:
以上是关于WPF:用主窗口生成了一个窗口,怎么在新窗口控制主窗口的textblock显示文字?的主要内容,如果未能解决你的问题,请参考以下文章