2010-03-03 12 views
9

Sto costruendo un'applicazione che deve consentire a un utente di inserire il testo da uno RichTextBox alla posizione attuale del cursore in un altro. Ho passato un sacco di tempo avvitamento intorno con modello a oggetti 's il FlowDocument prima di eseguire in tutta questa tecnica - source e target sono entrambi FlowDocument s:Come inserire contenuto in linea da un FlowDocument a un altro?

using (MemoryStream ms = new MemoryStream()) 
{ 
    TextRange tr = new TextRange(source.ContentStart, source.ContentEnd);      
    tr.Save(ms, DataFormats.Xaml); 
    ms.Seek(0, SeekOrigin.Begin); 
    tr = new TextRange(target.CaretPosition, target.CaretPosition); 
    tr.Load(ms, DataFormats.Xaml); 
} 

questo funziona molto bene.

L'unico problema che sto avendo ora è che inserisce sempre la sorgente come un nuovo paragrafo. Interrompe l'esecuzione corrente (o qualsiasi altra cosa) nel punto di inserimento, inserisce la sorgente e termina il paragrafo. Questo è appropriato se la fonte in realtà è un paragrafo (o più di un paragrafo), ma non se è solo una riga di testo (per esempio).

penso è probabile che la risposta a questo sta per finire per essere il controllo della destinazione per determinare se è costituita interamente da un unico blocco, e se lo fa, l'impostazione del TextRange a punto all'inizio e alla fine della bloccare il contenuto prima di salvarlo nel flusso.

L'intero mondo di FlowDocument è un mare di oscuri misteri oscuri. Posso diventare un esperto se devo (per Dostoevskij: "L'uomo è l'animale che può abituarsi a qualsiasi cosa."), Ma se qualcuno lo ha già capito e può dirmi come fare questo mi renderebbe la vita è molto più facile.

risposta

12

Il problema immediato è che si sta utilizzando TextFormat.Xaml anziché TextFormat.XamlPackage.

La proprietà che controlla se le linee vengono unite o meno quando i documenti vengono combinati è la proprietà Section.HasTrailingParagraphBreakOnPaste. Questa proprietà è solo efficace quando si carica o si salva il formato di testo XamlPackage. Quando si utilizza il formato di testo Xaml, la proprietà viene omessa durante Save() e ignorata durante Load().

Quindi la semplice correzione è quello di cambiare semplicemente il Load and Save chiamate:

tr.Save(ms, DataFormats.XamlPackage); 
ms.Seek(0, SeekOrigin.Begin); 
tr = new TextRange(target.CaretPosition, target.CaretPosition); 
tr.Load(ms, DataFormats.XamlPackage); 

Si noti che questo risolve anche un altro problema che si sarebbe alla fine incorrere in: bitmap incorporati non saranno copiati correttamente quando si utilizza DataFormats.Xaml perché ci è in nessun posto per mettere i bit di immagine. Con DataFormats.XamlPackage viene creato un intero pacchetto in modo che le bitmap e gli altri elementi del pacchetto possano apparire ok.

Una volta apportata questa modifica, potresti scoprire un altro fatto che potrebbe o meno essere un problema per te: il tuo codice di esempio utilizza document.ContentStart e document.ContentEnd. Se questo è il tuo codice reale, scoprirai che qualsiasi intervallo da document.ContentStart a document.ContentEnd consiste necessariamente di paragrafi completi, quindi la copia inserirà sempre un'interruzione di paragrafo alla fine dell'inserimento. Se questo è un problema, usare qualcosa come RichTextBox.Selection (se questo è UI guidato) o utilizzare TextPointer per eseguire il backup ContentEnd alla prima il segno di paragrafo implicita, ad esempio:

var tr = new TextRange(document.ContentStart, 
         document.ContentEnd.GetInsertionPosition(
                LogicalDirection.Backward)); 
+0

Sta andando un po 'prima che può effettivamente vai a controllare la correttezza, ma sembra proprio che tu sia stato esattamente dove sono ora, e apprezzo l'informazione. –