Search code examples
c#wpfstringflowdocument

Replace text in XamlPackage


I have some text in a RichTextBox. This text includes tags eg: [@TagName!]. I want to replace these tags with some data from a database without losing formatting (fonts, colors, image, etc). I've created a method:

 void ReplaceTagsWithData(FlowDocument doc)
    {
        FileStream fs = new FileStream("tmp.xml", FileMode.Create);
        TextRange trTextRange = 
            new TextRange(doc.ContentStart, doc.ContentEnd);

        trTextRange.Save(fs, DataFormats.Xaml);
        fs.Dispose();
        fs.Close();

        StreamReader sr = new StreamReader("tmp.xml");

        string rtbContent = sr.ReadToEnd();

        MatchCollection mColl = 
            Regex.Matches(rtbContent, 
                          string.Format(@"\{0}+[a-zA-Z]+{1}", 
                          prefix, 
                          postfix));

        foreach (Match m in mColl)
        {
            string colname = 
                m.Value.Substring(prefix.Length, 
                   (int)(m.Value.Length - (prefix.Length + postfix.Length)));

            rtbContent = rtbContent.Replace(m.Value.ToString(), 
                                            dt.Rows[0][colname].ToString());
        }

        rtbEdit.Document = 
            new FlowDocument(
                (Section)XamlReader.Load(
                    XmlReader.Create(new StringReader(rtbContent))));
        sr.Dispose();
        sr.Close();
    }

It's quite good but it removes images from content. I know that I should use XamlPackage instead of Xaml but then I can't get it as a plain text. Is there any other solution for this?

Thanks for answers. ;)

[EDIT: 13-02-2012 02:14(am)]

My working solution:

    void ReplaceTagsWithData(RichTextBox rtb)
{
    FlowDocument doc = rtb.Document;

    FileStream fs = new FileStream("tmp", FileMode.Create);
    TextRange trTextRange = new TextRange(doc.ContentStart, doc.ContentEnd);
    trTextRange.Save(fs, DataFormats.Rtf);
    fs.Dispose();
    fs.Close();

    StreamReader sr = new StreamReader("tmp");
    string rtbContent = sr.ReadToEnd();
    sr.Dispose();
    sr.Close();

    MatchCollection mColl = 
        Regex.Matches(rtbContent, 
                      string.Format(@"\{0}+[a-zA-Z]+{1}", 
                      prefix, 
                      postfix));

    foreach (Match m in mColl)
    {
        string colname = 
            m.Value.Substring(prefix.Length, 
                (int)(m.Value.Length - (prefix.Length + postfix.Length)));

        rtbContent = rtbContent.Replace(m.Value.ToString(), 
                                        dt.Rows[0][colname].ToString());
    }
    MemoryStream stream = 
        new MemoryStream(ASCIIEncoding.Default.GetBytes(rtbContent));
    rtb.SelectAll();
    rtb.Selection.Load(stream, DataFormats.Rtf);

}

Maybe it's not the best but it's working correctly.

It was solved. But I can't post solution because it is on company server which I can't access anymore.


Solution

  • You can use the Razor Engine to do whatever you want in the templating subject. You can download from nuget (http://www.nuget.org/packages/RazorEngine) and without any setup configuration you can use the Razor syntax to do this. For example your template can be this:

    <Window x:Class="<class>"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="@Model.Title"
            Icon="@Model.Icon">
      <Grid>    
      </Grid>
    </Window>
    

    Note: the @Model.Title and @Model.Icon thats come from Razor

    Actually i use RazorEngine to all my templating task: Email, Report generation on the fly (rdlc), etc...