C# 刷新绑定到console.stdout的文本块时出现WPF问题

C# 刷新绑定到console.stdout的文本块时出现WPF问题,c#,wpf,user-interface,console,refresh,C#,Wpf,User Interface,Console,Refresh,我正在用C#构建一个小的wpf应用程序。当第三次单击按钮时 party dll函数构造一个树状对象。这个对象是绑定的 到树上看。这工作正常,但需要一点时间来加载。作为 dll函数构造它将进度信息打印到 安慰我想把它重定向到一个文本块中,这样用户 获取以查看进度消息 我的窗口显示如下: InitializeComponent(); StringRedir s = new StringRedir(ref ProgressTextBlock); Console.SetOut(s); Consol

我正在用C#构建一个小的wpf应用程序。当第三次单击按钮时 party dll函数构造一个树状对象。这个对象是绑定的 到树上看。这工作正常,但需要一点时间来加载。作为 dll函数构造它将进度信息打印到 安慰我想把它重定向到一个文本块中,这样用户 获取以查看进度消息

我的窗口显示如下:

InitializeComponent(); StringRedir s = new StringRedir(ref ProgressTextBlock); Console.SetOut(s); Console.SetError(s); this.DataContext = s;
我相信问题出在StringRedir类的构造函数中。您正在传入ProgessTextBlock,并对其执行以下操作:

local.Text = "";
这实际上覆盖了ProgressTextBlock.Text的先前设置值,该值为:

{Binding Text}
明白我的意思吗?通过显式地为TextBlock的Text属性设置一个值,您已经取消了绑定


如果我读对了,那么将文本块传递到StringRedir的ctor中的想法似乎是在您尝试直接绑定之前的遗留问题。我会放弃这一点,坚持绑定的想法,因为它更符合WPF的“精神”。

您没有包含加载
TreeView
数据的代码,但我猜这是在UI线程上完成的。如果是这样,这将阻止任何UI更新(包括对
TextBlock
的更改),直到完成为止。

因此,在阅读了WPF线程模型()之后,我最终通过调用Dispatcher Invoke()并将调度优先级设置为Render来刷新它。正如Kent所说,调度程序队列中的UI更新可能优先级较低。我最后做了这样的事

XAML


C#目标更新处理程序代码

private void test_TargetUpdated(object sender, DataTransferEventArgs e) { TextBox t = sender as TextBox; t.ScrollToEnd(); t.Dispatcher.Invoke(new EmptyDelegate(() => { }), System.Windows.Threading.DispatcherPriority.Render); } 私有无效测试目标已更新(对象发送方、数据传输目标e) { TextBox t=发送方作为TextBox; t、 ScrollToEnd(); t、 Invoke(新的EmptyDelegate(()=>{})、System.Windows.Threading.DispatcherPriority.Render); } 注意:之前我使用的是文本块,但我改为文本框,因为它带有滚动

尽管如此,我仍然对整个流程感到不安。有更好的方法吗?
感谢马特和肯特的评论。如果我有分数,我会将他们的答案标记为有用。

谢谢马特。好的……这让我开始思考我在数据绑定方面做了些什么:)StringRedir类代码,我在msdn上找到,并盲目地认为我需要本地TextBlock引用来传递文本。哇,数据绑定…所以它就是这么做的:)如果它确实解决了问题,请不要忘记将此标记为答案。它肯定会这样做的。但我仍然没有看到textblock刷新(只有在整个treeview加载后才会刷新)。我已经从StringRedir类中删除了本地TextBlock,现在只依赖绑定。使用2008 express edition,没有调试线程窗口。我知道TextBlock.Text已更新(它正在触发TargetUpdated事件)。我只需要它自己重新绘制。尝试了所有的invalidate方法,但它们似乎是异步的,或者可能是低优先级的。需要强制重画的方法如果要处理来自UI线程的所有UI消息,请在此处查看我的帖子:。它将向您展示如何在WPF中实现DoEvents()。设置好文本后再打电话,你应该会没事的。哈!我刚刚发布了一个关于Dispatcher Invoke的答案。我会查看你的帖子。谢谢你的帮助。非常感谢。
{Binding Text}
<TextBox VerticalScrollBarVisibility="Auto"  
         Text="{Binding Path=Text, NotifyOnTargetUpdated=True}"
         x:Name="test" TextWrapping="Wrap" AcceptsReturn="True" 
         TargetUpdated="test_TargetUpdated"/>
private void test_TargetUpdated(object sender, DataTransferEventArgs e) { TextBox t = sender as TextBox; t.ScrollToEnd(); t.Dispatcher.Invoke(new EmptyDelegate(() => { }), System.Windows.Threading.DispatcherPriority.Render); }