I noticed the snapshot feature, and the lack of a setter on the snapshot does make sense. You could still have a text getter on the document or SE to provide parallelism. For user who don't use snapshots, they may find it confusing or frustrating to have to drop down to that level to get text out of the control.
WRT #3, I am building an IDE. I have a proprietary XML-based language that describes a solution. I also have graphical designers for the solution. Think of the XAML editor in VS and the split view that keeps the graphical designer and XML editor in sync dynamically (except our syncing works a lot better :-)).
OK, so with that context, we do all of my synching with WPF data binding against a backend engine. That is, both the XML editor and the designers bind to the engine, not directly to each other. This makes everything run very smoothly (integrated undo/redo stacks, background compilation and recompile, and a bunch of other stuff).
Now consider that we have to keep things in sync, but we have to do somewhat different things depending on whether a change came from the designer or the SE. If it came from the designer, we need to emit changes to the engine object model and then render the appropriate XML fragment into the SE. If it came from the SE, we need to parse the text and then merge object model changes into the engine.
See how this can get into an infinite loop. You change the designer which renders text, which triggers a text update, which triggers a parse, which updates the OM, which updates the designer, etc. The IsLastChangeProgrammatic property is our guard to break the recursion.
Of course, I'm totally open to doing it differently if there is something else that has a similar effect.