3

I'm developing a C#/Xaml UWP text editing app that uses the RichEditBox control for editing text files from. However, I've noticed when I load larger files (~1mb and above, perhaps even less) that the control struggles in a couple of key areas: 1) it takes a while to load the contents of the file and 2) once it finally has, scrolling is very jerky and input into the file is neither smooth nor responsive.

The closest answer I've come across is this (what it describes is exactly the problem I'm having) but it doesn't appear to be applicable to a UWP app.

EDIT:

When I open a file, the noteworthy code to share is:

_currentFile.Content = await readFile(file);
_currentFile._richeditbox.Document.SetText(TextSetOptions.None, _currentFile.Content);

This is the readFile() function, which was helped via 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;
} 

When debugging, there's absolutely no delay when the readFile() function is called; it gets executed very quickly.

I've tried loading a 1.14mb text file. It takes some time to load, and when it does although the scrollbar height indicates all of it has loaded, it actually doesn't display any text from line 2098 onwards (there are 3,771 lines in total); it stops at this line consistently even on subsequent reloads.

See picture:

enter image description here

As you can also see the last line that is visible gets mashed up with the line above it.

For reference, the file I'm having the problems with can be downloaded from here (but to be clear it's a problem with all text files of a similar size, and possibly much less even): http://mtrostyle.net/appytext/testfile.txt.

Barrrdi
  • 902
  • 13
  • 33
  • I have try to load a 138M size rtf file. However, I could not reproduce your issue. Could you share more code about how do you load the file? – Nico Zhu Aug 02 '17 at 03:06
  • I've updated with noteworthy code and other info. Thanks for looking into this Nico, much appreciated. – Barrrdi Aug 02 '17 at 10:41

1 Answers1

0

Yes, I get the same result in my side when I load you provide txt file. I has been reporting this issue to related team. Currently, one workaround to show the file is that render the text in the WebView control. And the set import and export for the WebView. For more you could refer to 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);
}
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • 1
    Hmm, okay, at least that's good in that the issue is reproducible. Thanks for sharing it with the relevant team too, hopefully this can get resolved as I consider this to be a fundamental requirement for all text editing apps on the Store i.e. many apps. With your suggestion though, firstly I'm using Xaml, and not JS. Is the JS code to be inserted into the HTML file that the Webview is meant to render? And what do I do in order to make the text editable? Do I copy the contents of the Webview to the RichEditBox? Obviously this isn't ideal and if it does work I would limit to big files only. – Barrrdi Aug 03 '17 at 11:16
  • May also be worth pointing out that I did come across another Stack Overflow question that reads very similar to mine: https://stackoverflow.com/questions/18668920/c-sharp-richeditbox-has-extremely-slow-performance-4-minutes-loading. What's interesting is it looks like this has been a problem for some time. It actually had a solution but unfortunately doesn't apply to UWP (I don't think). But perhaps it can be something of a lead for you/others looking into this. – Barrrdi Aug 03 '17 at 12:27
  • Yes. I'd love to hear your suggestions. And the above answer is complete, it provide a complete input and output feature via ScriptNotify method. However, it is indeed a temporary solution! I look forward to your more feedback so that we can improve our quality. Best regards. – Nico Zhu Aug 04 '17 at 09:01
  • 1
    Hi guys. As of now a project I'm involved with is suffering from jittery scroll as we are using a lot of richeditbox as datatemplates for a GRIDVIEW with a lot of items. And even though we have very small data per item, we are getting very bad performance during scroll, the contents in the richeditbox takes too long to load. Please help with this and share if there has been any new development regarding improving performance of richeditbox data loading – Skynet094 Sep 05 '19 at 01:52