Share via


More on "Avalon" RichTextBox

As promised, I learned more so I'm sharing. Last time I figured out how to stuff plain text into the RichTextBox, but that's not very "rich", is it? 

How do I put RTF (rich text format) into a RichTextBox?
It turns out the support for this seems to be through the TextRange class. TextRange offers a "Load" method which takes a string representing a data format (which you can pick from the DataFormats class) and a stream. If you currently have a string of RTF formatting, you can stuff the string in a MemoryStream, then pass it to the TextRange. Here's a handy helper function for it:

        private static void LoadRTF(string rtf, RichTextBox richTextBox) {

            if (string.IsNullOrEmpty(rtf)) {
throw new ArgumentNullException();
}

            TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);

            //Create a MemoryStream of the Rtf content

using (MemoryStream rtfMemoryStream = new MemoryStream()) {
using (StreamWriter rtfStreamWriter = new StreamWriter(rtfMemoryStream)) {
rtfStreamWriter.Write(rtf);
rtfStreamWriter.Flush();
rtfMemoryStream.Seek(0, SeekOrigin.Begin);

                    //Load the MemoryStream into TextRange ranging from start to end of RichTextBox.
textRange.Load(rtfMemoryStream, DataFormats.Rtf);
}
}
}

How do I load a file with "rich" content in it?
Here again, you can use the TextRange class to load, but you pass in a FileStream instead of a MemoryStream. 

   private static void LoadFile(string filename, RichTextBox richTextBox) {
if (string.IsNullOrEmpty(filename)) {
throw new ArgumentNullException();
}
if (!File.Exists(filename)) {
throw new FileNotFoundException();
}

            // open the file for reading
using (FileStream stream = File.OpenRead(filename)) {
// create a TextRange around the entire document
TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);

// sniff out what data format you've got
string dataFormat = DataFormats.Text;
string ext = System.IO.Path.GetExtension(filename);
if (String.Compare(ext, ".xaml",true) == 0) {
dataFormat = DataFormats.Xaml;
}
else if (String.Compare(ext, ".rtf", true) == 0) {
dataFormat = DataFormats.Rtf;
}
documentTextRange.Load(stream, dataFormat);
}
}

How do I Save a file with "rich" content in it?
TextRange also has a Save! Here's the code

    private static void SaveFile(string filename, RichTextBox richTextBox) {
if (string.IsNullOrEmpty(filename)) {
throw new ArgumentNullException();
}
          

            // open the file for reading
using (FileStream stream = File.OpenWrite(filename)) {
// create a TextRange around the entire document
TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);

                // sniff out what data format you've got
string dataFormat = DataFormats.Text;
string ext = System.IO.Path.GetExtension(filename);
if (String.Compare(ext, ".xaml", true) == 0) {
dataFormat = DataFormats.Xaml;
}
else if (String.Compare(ext, ".rtf", true) == 0) {
dataFormat = DataFormats.Rtf;
}
documentTextRange.Save(stream, dataFormat);
}
}

Putting it all together - a very simple editor

Replacing the contents of the Window with this DockPanel, adding the SaveFile, LoadFile helper methods and the event handlers for open and save, we can get a very simple rich text editor.

<!-- Window1.xaml -->
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="_Open File" Click="OnOpenFile"/>
<MenuItem Header="_Save" Click="OnSaveFile"/>
<Separator/>
<MenuItem Header="E_xit" Click="OnExit"/>
</MenuItem>
</Menu>
<RichTextBox Name="richTextBox1"></RichTextBox>
</DockPanel>

        // Window1.xaml.cs
private void OnExit(object sender, EventArgs e) {
this.Close();
}
private void OnOpenFile(object sender, EventArgs e) {
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
ofd.Filter = "Text Files (*.txt; *.xaml; *.rtf)|*.txt;*.xaml;*.rtf";
ofd.Multiselect = false;
if (ofd.ShowDialog() == true) {
LoadFile(ofd.SafeFileName, richTextBox1);
}

        }
private void OnSaveFile(object sender, EventArgs e) {
Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
sfd.Filter = "Text Files (*.txt; *.xaml; *.rtf)|*.txt;*.xaml;*.rtf";
if (sfd.ShowDialog() == true) {
SaveFile(sfd.SafeFileName, richTextBox1);
}
}

Comments

  • Anonymous
    January 16, 2006
    Thanks for the info, looks great!

    When are we going to see (x)HTML support? Very very very few people use RTF anymore, HTML is the standard and MSHTML.dll is getting VERY long in the tooth.

    Sometime soon I hope!
  • Anonymous
    January 17, 2006
    Is this post-December CTP because I can not find TextRange.Load and TextRange.Save methods in my installation of these bits?
  • Anonymous
    January 17, 2006
    The comment has been removed
  • Anonymous
    January 17, 2006
    Thanks James! Re XHTML, you might want to suggest it over on the avalon MSDN forum...
    https://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&SiteID=1
  • Anonymous
    January 17, 2006
    Aha, Paul yes this looks to be new methods to look forward to in the next CTP - these replace TextRange.Xml.
  • Anonymous
    January 21, 2006
    Jessica,the WINFX SDK January CTP download link doesn't work in my region, can you report this problem up to the WINFX team?
    Hopefully they can fix the download link as soon as possible.

    Sheva
  • Anonymous
    January 21, 2006
    RE: WINFX SDK/January CTP, it looks like this is expected:

    http://www.microsoft.com/downloads/details.aspx?FamilyId=61DD9CA7-1668-42E4-BD37-03716DD83E53&displaylang=en

    Additional Information
    This January CTP is for English only. If you are targeting a non-English platform or if you wish to view WinFX resources in a different language, you will need to use the December CTP. You can then download the appropriate language version of the WinFX language pack. The December CTP language packs are available in German and Japanese.

    この January CTP は英語のみです。英語以外のプラットフォームを対象にする場合、または異なる言語で WinFX リソースを表示する場合は、December CTP を使用してください。その後、WinFX Language Pack の適切な言語バージョンをダウンロードすることができます。この December CTP では、ドイツ語および日本語の Language Pack を利用することができます。

    Der CTP vom Januar ist nur auf Englisch verfügbar. Wenn Sie auf einer nicht-englischen Plattform installieren oder WinFX-Ressourcen in einer anderen Sprache anzeigen möchten, müssen Sie den CTP vom Dezember verwenden. Sie können sich dann die entsprechende Sprachversion des WinFX Language Packs herunterladen. Die Language Packs für den Dezember-CTP sind auf Deutsch und Japanisch verfügbar.
  • Anonymous
    January 21, 2006
    Well, I think you don't get into what I meant previously.
    when I followed the SDK download link, I got this in my browser:
    Internal Server Error - Read
    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Reference #3.13dc4bca.1137898399.c131d6

    probably you can try it yourself:
    http://www.microsoft.com/downloads/details.aspx?familyid=64750EEF-D4A7-4CC8-92F2-9A201268A231&displaylang=en
  • Anonymous
    January 23, 2006
    Ah OK, I am not seeing this myself... I'll send it on.

    FYI: You can still use productfeedback to send in bug reports:

    http://lab.msdn.microsoft.com/productfeedback/SearchResults.aspx?text=&stype=1&fields=1&type=0&witId=0&pId=17&category=0&os=0&oslang=0&status=0&msstatus=0&resolution=0&chgdays=&validation=0&votes=&voterating=0&workarounds=False&attachments=False
  • Anonymous
    February 14, 2006
    I thought I'd put up a few good reads:

    Mapping PIs are going away in the next CTP. Rob promises to...
  • Anonymous
    February 18, 2007
    Here is a simple function that will convert RTF data on the clipboard to XAML: /// &lt;summary&gt; ///