我想使用WPF-RichTextbox
BackgroundWorker
中加载文字文件
这是我的代码:
private delegate void update();
private void reader()
{
StreamReader str = new StreamReader("C:\\test.txt");
while (!str.EndOfStream)
{
richTextBox1.AppendText(str.ReadToEnd());
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
progress wnd = new progress();
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += delegate(object s, DoWorkEventArgs args)
{
update up = new update(reader);
richTextBox1.Dispatcher.Invoke(up);
};
bg.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
wnd.Close();
};
wnd.Show();
bg.RunWorkerAsync();
}
和progress.xaml:
<Window x:Class="WpfApplication3.progress"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="progress" Height="192" Width="452" ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True" WindowStartupLocation="CenterScreen" WindowStyle="None">
<Grid>
<Label Content="loading ...." Height="28" HorizontalAlignment="Left" Margin="46,32,0,0" Name="label1" VerticalAlignment="Top" />
<ProgressBar Height="29" HorizontalAlignment="Left" Margin="46,78,0,0" Name="progressBar1" VerticalAlignment="Top" Width="325" IsIndeterminate="True" />
</Grid>
当我设置wnd.showdialog()
时,它会显示进度条的不确定状态,但应用程序不会加载任何文本。
当我设置wnd.show()
时,它会加载文本,但加载时,进度条会冻结
没有表现出不确定的状态。
感谢您的帮助。
编辑:
由于Servey和SLaks的答案,我更新了代码,但它有同样的问题(它加载文本但加载时,进度条冻结,并且不显示不确定状态。)
有什么问题?这是我更新的代码:
StringBuilder sb = new StringBuilder();
private void reader()
{
StreamReader str = new StreamReader("C:\\test.txt");
while (!str.EndOfStream)
{
sb.Append(str.ReadToEnd());
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
progress wnd = new progress();
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += delegate(object s, DoWorkEventArgs args)
{
reader();
};
bg.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
richTextBox1.AppendText(sb.ToString());
wnd.Close();
};
wnd.Show();
bg.RunWorkerAsync();
}
答案 0 :(得分:1)
你实际上并没有在后台做任何工作。您正在启动后台工作程序,而后台工作人员在后台执行的唯一操作就是安排在UI线程上运行的操作,并且该操作是您执行所有非UI工作的地方。由于您在UI线程上进行非UI工作,因此在完成之前不能执行任何其他图形操作。
您需要从BGW的do work事件中读取文件,将其存储在内存中,然后在UI线程中运行的Completed事件中,然后将该数据放入UI中。
答案 1 :(得分:1)
好的,我已经查看了您上传的代码,您的问题很可能与您的负载有关。就您的加载而言,以下代码可以按您的要求完成工作:
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
Loaded -= OnLoaded;
var wnd = new ProgressWindow();
var dispatcher = wnd.Dispatcher;
Task.Factory.StartNew(() =>
{
using (var stream = new StreamReader("C:\\test.txt"))
return stream.ReadToEnd();
}).ContinueWith(x =>
{
//Main window dispatcher
Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => richTextBox1.AppendText(x.Result)));
//progress window dispatcher
dispatcher.Invoke(DispatcherPriority.DataBind, new Action(wnd.Close));
});
wnd.ShowDialog();
}
虽然这可以按预期工作,但无论如何都会发生冻结(我冻结了几秒钟加载一个800kb的文本文件)。问题是您使用RichTextBox。根据您的代码判断,您不知道wfp是如何工作的,并且您正在尝试以典型的winform风格工作。
Wpf中的 RichTextBox
与winforms RichTextBox
非常不同。同样,TextBlock
与典型的Label
非常不同。如果您想要的只是颜色和其他格式选项,TextBlock
能够独立完成此操作,并且比构建RichTextBox
的方式快得多。
如果您必须从文本文件构建RichTextBox
,则需要了解FlowDocument
以及如何自己创建文本文件以避免冻结。这个解决方案的替代方案是运行两个UI线程(每个窗口一个),你很可能会发现它比它的价值更麻烦。
在尝试此类事情之前,您应该先排序WPF基础知识并学习典型的MVVM模式,然后再深入了解WPF世界。再次,如果可以,请避免在WPF中使用RTB。如果您知道如何使用它们,WPF中的基本控件比它们的winforms功能强大得多。