我正在用C#构建一个小型的wpf应用程序。按下按钮时,第三个按钮 party dll函数构造一个类似于对象的树。这个对象是绑定的 到树视图。这工作正常但需要一些时间来加载。作为 dll函数构造它打印进度信息的对象 安慰。我想将其重定向到TextBlock以便用户 得到进展信息。
我的窗口ctor看起来像这样:
InitializeComponent(); StringRedir s = new StringRedir(ref ProgressTextBlock); Console.SetOut(s); Console.SetError(s); this.DataContext = s;
xaml:
<
TextBlock Text="{Binding Path=Text}" Width="244" x:Name="ProgressTextBlock" TextWrapping="Wrap" /><
TreeView >...<
/TreeView>
StringRedir类如下所示。问题是TextBlock for 某些原因直到TreeView才会更新消息 得到了加载。单步执行我看到Text属性正在更新 但TextBlock没有刷新。我添加了一个MessageBox.Show ()在Text更新的时候,这似乎导致了 窗口每次刷新,我能够看到每条消息。所以我 我想我需要一些方法来明确刷新屏幕...但是这个 没有意义我认为数据绑定会导致视觉 属性更改时刷新。我在这里错过了什么?我如何能 让它刷新?任何建议表示赞赏!
public class StringRedir : StringWriter , INotifyPropertyChanged
{
private string text;
private TextBlock local;
public string Text {
get{ return text;}
set{
text = text + value;
OnPropertyChanged("Text");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public StringRedir(ref TextBlock t)
{
local = t;
Text = "";
}
public override void WriteLine(string x)
{
Text = x +"\n";
//MessageBox.Show("hello");
}
}
答案 0 :(得分:1)
您没有包含加载TreeView
数据的代码,但我猜它是在UI线程上完成的。如果是这样,这将阻止任何UI更新(包括对TextBlock
的更改),直到完成为止。
答案 1 :(得分:1)
因此,在对WPF线程模型(http://msdn.microsoft.com/en-us/library/ms741870.aspx)进行一些阅读之后,我终于通过调用Dispatcher Invoke()并将Dispatch priority设置为Render来刷新它。正如Kent建议的那样,调度程序队列中的UI更新可能是低优先级的。我最终做了这样的事情。
XAML
<TextBox VerticalScrollBarVisibility="Auto"
Text="{Binding Path=Text, NotifyOnTargetUpdated=True}"
x:Name="test" TextWrapping="Wrap" AcceptsReturn="True"
TargetUpdated="test_TargetUpdated"/>
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); }
注意:早些时候我使用的是TextBlock,但我更改为TextBox,因为它带有滚动
但是,我仍然对整个流程感到不安。有一个更好的方法吗? 感谢Matt和Kent的评论。如果我有分数会将他们的答案标记为有帮助。答案 2 :(得分:0)
我认为问题出在你的StringRedir类的构造函数中。你正在传递ProgessTextBlock,你正在这样做:
local.Text = "";
这实际上是覆盖以前为ProgressTextBlock.Text设置的值,这是:
{Binding Text}
明白我的意思?通过显式设置TextBlock的Text属性值,您已取消绑定。
如果我正确阅读,看起来将TextBlock传递给StringRedir的ctor的想法是在您尝试直接绑定之前的宿醉。我倾向于坚持并坚持具有约束力的想法,因为它更多地体现在WPF的“精神”中。