Производительность RichEditBox снижается при работе с большими текстовыми файлами (загрузка + прокрутка)
Я занимаюсь разработкой приложения для редактирования текста на C#/Xaml UWP, которое использует элемент управления RichEditBox для редактирования текстовых файлов. Тем не менее, я заметил, когда я загружаю большие файлы (~1 МБ и выше, возможно, даже меньше), что элемент управления борется в нескольких ключевых областях: 1) требуется некоторое время для загрузки содержимого файла и 2) как только он наконец, прокрутка очень резкая, и ввод в файл не является ни плавным, ни отзывчивым.
Самый близкий ответ, с которым я столкнулся, заключается в следующем (то, что он описывает, это как раз та проблема, с которой я столкнулся), но, похоже, он не применим к приложению UWP.
РЕДАКТИРОВАТЬ:
Когда я открываю файл, стоит отметить следующий код:
_currentFile.Content = await readFile(file);
_currentFile._richeditbox.Document.SetText(TextSetOptions.None, _currentFile.Content);
Это функция readFile(), которая помогла через https://social.msdn.microsoft.com/Forums/sqlserver/en-US/0f3cd056-a2e3-411b-8e8a-d2109255359a/uwpc-reading-ansi-text-file?forum=wpdevelop:
private async Task<string> readFile(StorageFile file)
{
string charSet = null;
try
{
await Task.Run(() =>
{
try
{
using (FileStream fs = System.IO.File.OpenRead(file.Path))
{
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(fs);
cdet.DataEnd();
charSet = cdet.Charset;
}
}
catch (Exception ex)
{
}
});
}
catch (Exception e)
{
}
Classes.File._lastEncoding = charSet;
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string content = "";
if (charSet == "windows-1252")
{
content = Encoding.GetEncoding("iso-8859-1").GetString(fileContent, 0, fileContent.Length);
}
else if (charSet == "UTF-16LE")
{
content = Encoding.Unicode.GetString(fileContent, 0, fileContent.Length);
}
else if (charSet == "UTF-16BE")
{
content = Encoding.BigEndianUnicode.GetString(fileContent, 0, fileContent.Length);
}
else
{
content = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
}
return content;
}
При отладке нет абсолютно никакой задержки при вызове функции readFile(); это выполняется очень быстро.
Я попытался загрузить текстовый файл 1.14 МБ. Загрузка занимает некоторое время, и когда это происходит, хотя высота полосы прокрутки указывает на то, что она полностью загружена, она фактически не отображает никакого текста, начиная со строки 2098 и далее (всего 3771 строка); он останавливается на этой линии последовательно даже при последующих перезагрузках.
Смотрите картинку:
Как вы также можете видеть, последняя видимая строка растирается со строкой над ней.
Для справки: файл, с которым у меня возникли проблемы, можно скачать отсюда (но, чтобы было ясно, это проблема со всеми текстовыми файлами одинакового размера, и, возможно, намного менее ровными): http://mtrostyle.net/appytext/testfile.txt.
1 ответ
Да, я получаю тот же результат на моей стороне, когда я загружаю предоставленный вами текстовый файл. Я сообщал об этой проблеме в соответствующую команду. В настоящее время одним из способов показать файл является отображение текста в WebView
контроль. И набор импорта и экспорта для WebView
, Для более вы можете обратиться к WebView
,
<body>
<textarea id="input" style="width:100%; height:400px;"></textarea>
<script type="text/javascript">
function SetText(text) {
document.getElementById('input').textContent = text;
}
function SaveText() {
var note = document.getElementById('input').textContent;
window.external.notify(note);
}
</script>
</body>
MainPage.xaml
<WebView x:Name="MyWebView" Source="ms-appx-web:///HomePage.html" Height="400" />
MainPage.xaml.cs
public MainPage()
{
this.InitializeComponent();
MyWebView.ScriptNotify += MyWebView_ScriptNotify;
}
private void MyWebView_ScriptNotify(object sender, NotifyEventArgs e)
{
var saveText = e.Value.ToString();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Pickers.FileOpenPicker open =
new Windows.Storage.Pickers.FileOpenPicker();
open.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
open.FileTypeFilter.Add(".rtf");
open.FileTypeFilter.Add(".txt");
Windows.Storage.StorageFile file = await open.PickSingleFileAsync();
if (file != null)
{
var Content = await readFile(file);
string[] args = { Content };
await MyWebView.InvokeScriptAsync("SetText", args);
}
}
private async Task<string> readFile(StorageFile file)
{
string charSet = null;
try
{
await Task.Run(async () =>
{
try
{
using (var fs = await file.OpenAsync(FileAccessMode.Read))
{
var tem = fs.AsStream();
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(tem);
cdet.DataEnd();
charSet = cdet.Charset;
}
}
catch (Exception ex)
{
}
});
}
catch (Exception e)
{
}
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string content = "";
if (charSet == "windows-1252")
{
content = Encoding.GetEncoding("iso-8859-1").GetString(fileContent, 0, fileContent.Length);
}
else if (charSet == "UTF-16LE")
{
content = Encoding.Unicode.GetString(fileContent, 0, fileContent.Length);
}
else if (charSet == "UTF-16BE")
{
content = Encoding.BigEndianUnicode.GetString(fileContent, 0, fileContent.Length);
}
else
{
content = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
}
return content;
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
await MyWebView.InvokeScriptAsync("SaveText", null);
}