2011-04-28 14 views
11

Qual è il modo migliore per rilevare se un RichTextBox/FlowDocument WPF è vuoto?Rileva se un RichTextBox è vuoto

Il seguente funziona se solo il testo è presente nel documento. Non se contiene di UIElement

new TextRange(Document.ContentStart, Document.ContentEnd).IsEmpty 

risposta

13

Si potrebbe confrontare i puntatori, che non è troppo affidabile:

var start = rtb.Document.ContentStart; 
var end = rtb.Document.ContentEnd; 
int difference = start.GetOffsetToPosition(end); 

Questo restituisce 2 se la RTB è caricato, e 4 se il contenuto è stato inserito e rimosso di nuovo.
Se l'RTB viene completamente eliminato, ad es. via select all -> delete il valore sarà 0.


Nel Silverlight reference on MSDN un altro metodo è trovato che può essere adattato e migliorato per:

public bool IsRichTextBoxEmpty(RichTextBox rtb) 
{ 
    if (rtb.Document.Blocks.Count == 0) return true; 
    TextPointer startPointer = rtb.Document.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward); 
    TextPointer endPointer = rtb.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward); 
    return startPointer.CompareTo(endPointer) == 0; 
} 
+0

Il conteggio è uno anche se il RichTextBox è vuoto. –

+0

Hmm, questo ha davvero senso ... –

+0

Ho modificato la mia risposta per mostrare un altro approccio, è un po 'strano però. –

0

La risposta di cui sopra funziona se non si mette qualcosa in RTB. Tuttavia, se si elimina semplicemente il contenuto, la RTB tende a restituire un singolo paragrafo vuoto, non una stringa completamente vuota. Quindi, questo è più affidabile in questi casi:

string text = new TextRange(Document.ContentStart, Document.ContentEnd).Text; 
return !String.IsNullOrWhiteSpace(text); 

Questo vale solo per testuali contenuti, naturalmente.

3

La risposta di H.B. non è utile se è necessario distinguere tra immagini e spazi vuoti. È possibile utilizzare qualcosa come this answer per verificare le immagini.

bool IsEmpty(Document document) 
{ 
    string text = new TextRange(Document.ContentStart, Document.ContentEnd).Text; 
    if (string.IsNullOrWhiteSpace(text) == false) 
     return false; 
    else 
    { 
     if (document.Blocks.OfType<BlockUIContainer>() 
      .Select(c => c.Child).OfType<Image>() 
      .Any()) 
     return false; 
    } 
    return true; 
} 

Questo sembra laborioso, e probabilmente non è corretto per tutti gli scenari. Ma non sono riuscito a trovare un modo migliore.

0

Prima - grazie a McGarnagle - la loro risposta mi ha fatto andare nella giusta direzione. Comunque per qualsiasi ragione il loro controllo dell'immagine non ha funzionato per me. Questo è quello che ho finito per fare:

Private Function RichTextBoxIsEmpty(BYVAL rtb As RichTextBox) As Boolean 

    Dim ReturnCode As Boolean = True 

    Dim text As String = New TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd).Text 

    If String.IsNullOrWhiteSpace(text) Then 

     For Each block As Block In rtb.Document.Blocks 

      'check for an image 
      If TypeOf block Is Paragraph Then 
       Dim paragraph As Paragraph = DirectCast(block, Paragraph) 
       For Each inline As Inline In paragraph.Inlines 
        If TypeOf inline Is InlineUIContainer Then 
         Dim uiContainer As InlineUIContainer = DirectCast(inline, InlineUIContainer) 
         If TypeOf uiContainer.Child Is Image Then 
          ReturnCode = False 
          Exit For 
         End If 
        End If 
       Next 
      End If 

      ' Check for a table 
      If TypeOf block Is Table Then 
       ReturnCode = False 
       Exit For 
      End If 

     Next 

    Else 

     ReturnCode = False 

    End If 

    Return ReturnCode 

End Function 

ci possono essere altri controlli da fare, ma questo almeno si estende su testo, immagini e tabelle.

0

Ecco un'estensione dell'idea di H.B. che funziona sia con il testo che con le immagini.

Ho trovato che la differenza è sempre> 4 ogni volta che l'RTB ha testo. Tuttavia, se si incolla solo un'immagine è 3. Per combatterla, osservo la lunghezza della stringa raw rtf.

var start = Document.ContentStart; 
var end = Document.ContentEnd; 
var difference = start.GetOffsetToPosition(end); 

HasText = difference > 4 || GetRtfText().Length > 350; 


public string GetRtfText() 
{ 
    var tr = new TextRange(Document.ContentStart, Document.ContentEnd); 
    using (var ms = new MemoryStream()) 
    { 
    tr.Save(ms, DataFormats.Rtf); 
    return Encoding.Default.GetString(ms.ToArray()); 
    } 
} 

Attraverso il mio test ho trovato che una scatola vuota, senza caratteri ha una lunghezza di 270. Se ho anche incollare in un'immagine che è solo 1 pixel in termini di dimensioni che palloncini per 406.

ho giocato con passare su varie opzioni di formattazione senza digitare alcuna lettera e non sono arrivati ​​a 300, quindi sono andato con 350 per la linea di base.

Il controllo della lunghezza può essere costoso se non ci sono caratteri testuali, ma sono incollati in un'immagine massiccia.