1

I want to compare a FlowDocument to a document of Rich Text Box. Here is the code

if (rtbEditor.Document != (XamlReader.Parse(currentNote.content) as FlowDocument))
{
   MessageBox.Show("Overwrite existing Note?", "Save", MessageBoxButton.OKCancel);
}

At the beginning I set rtbEditor's document as

rtbEditor.Document = XamlReader.Parse(currentNote.content) as FlowDocument;

Thus, unless the content of rtbEditor is changed, I thought that the if statement should not execute,but it does. Probably this is not the way to compare FlowDocuments. If this is not the correct way then how can we compare two documents?

If it is necessary, the currentNote.content is a string containing xml content of FlowDocument.

Tamir Vered
  • 10,187
  • 5
  • 45
  • 57
ozgur
  • 2,549
  • 4
  • 25
  • 40
  • It is comparing two objects and those are different objects. I bet if you created two XamlReader.Parse(currentNote.content) as FlowDocument they not even be the same. – paparazzo Oct 07 '15 at 17:49
  • @Frisbee I know. I just posted the code, because that is the only way I could think of. – ozgur Oct 07 '15 at 19:45
  • Could could either of the two `FlowDocument` instances have embedded bitmaps? – dbc Oct 07 '15 at 19:49
  • @dbc No. They are just text related xml elements. Actually content is very simple. Only forecolor, boldness and stuff like that are set. – ozgur Oct 07 '15 at 19:55

1 Answers1

1

Assuming you have no images in your FlowDocument instances, you can just serialize to XAML and compare the XAML. First, create extension methods to generate the XAML strings:

public static class FrameworkContentElementExtensions
{
    public static string ToXaml(this FrameworkContentElement element) // For instance, a FlowDocument
    {
        if (element == null)
            return null;
        var sb = new StringBuilder();
        using (var xmlWriter = XmlWriter.Create(sb))
        {
            XamlWriter.Save(element, xmlWriter);
        }
        return sb.ToString();
    }

    public static string ToFormattedXamlString(this FrameworkContentElement element)
    {
        if (element == null)
            return null;
        var settings = new XmlWriterSettings() { Indent = true, IndentChars = "    " };
        var sb = new StringBuilder();
        using (var xmlWriter = XmlWriter.Create(sb, settings))
        {
            XamlWriter.Save(element, xmlWriter);
        }
        return sb.ToString();
    }
}

Then you can do

if (rtbEditor.Document.ToXaml() != currentNote.content)
{
   MessageBox.Show("Overwrite existing Note?", "Save", MessageBoxButton.OKCancel);
}

Note that if the XAML differs only because of cosmetic formatting (XML indentation), since XAML documents are valid XML, you can parse your XAML to an XElement and use XNode.DeepEquals(). You can also serialize a FrameworkContentElement directly to an XElement without the intervening string representation for improved performance:

public static class FrameworkContentElementExtensions
{
    public static XElement ToXamlXElement(this FrameworkContentElement element) // For instance, a FlowDocument
    {
        if (element == null)
            return null;
        var doc = new XDocument();
        using (var xmlWriter = doc.CreateWriter())
        {
            XamlWriter.Save(element, xmlWriter);
        }
        var xElement = doc.Root;
        if (xElement != null)
            xElement.Remove();
        return xElement;
    }
}

And then

var docXaml = rtbEditor.Document.ToXamlXElement();
var currentNoteXaml = XElement.Parse(currentNote.content);
if (!XNode.DeepEquals(docXaml, currentNoteXaml))
{
   MessageBox.Show("Overwrite existing Note?", "Save", MessageBoxButton.OKCancel);
}

If you are concerned there might be embedded messages and want to generate a warning message in this case, see Finding all Images in a FlowDocument.

dbc
  • 104,963
  • 20
  • 228
  • 340