2012-01-20 11 views
34

Ci sono un sacco di domande simili su internet, su SO incluso, ma le soluzioni proposte non funzionano nel mio caso. Scenario: v'è una casella di testo di log in XAMLCasella di testo multilinea con scorrimento verticale automatico

<TextBox Name="Status" 
      Margin="5" 
      Grid.Column="1" 
      Grid.Row="5" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Width="600" 
      Height="310"/> 

ci sono metodi in code-behind che fare un certo lavoro e aggiungere un po multilinea (forse questo è il problema?) I messaggi in questo campo testo:

private static void DoSomeThings(TextBox textBox) 
{ 
    // do work 
    textBox.AppendText("Work finished\r\n"); // better way than Text += according to msdn 
    // do more 
    textBox.AppendText("One more message\r\n"); 
    ... 
} 

private static void DoSomething2(TextBox textBox) 
{ 
    // same as first method 
} 

È necessario scorrere fino alla fine della casella di testo dopo che tutte le azioni sono state eseguite. Provato ScrollToEnd(), ScrollToLine, avvolgendo textbox in ScrollViewer, selezione e caret workaround, allegando ScrollToEnd a TextChanged. Nessuno di questi funziona, dopo che le righe di esecuzione che superano l'altezza del textbox devono ancora essere fatte scorrere manualmente. Ci scusiamo per la doppia domanda, credo che mi manchino alcuni problemi minori che possono essere risolti rapidamente da qualcuno che ha una nuova visione del problema. Grazie in anticipo.

+0

Quando si dice che è necessario "scorrere fino al [la] parte inferiore di [the] textbos", si intende veramente "scorrimento" come in "l'ultimo testo aggiunto è completamente visibile"? O vuoi che il cursore si trovi alla fine della casella di testo? –

+0

Primo. Per illustrare fatto uno screenshot - a sinistra è quello che ottengo, giusto è quello che mi serve (come scorrere manualmente verso il basso): http://i.piccy.info/i7/0c105234c75b7031df050587f72771b4/1-5-3848/56682026/120120114019_6.jpg – Jaded

risposta

73

Secondo questa domanda: TextBox.ScrollToEnd doesn't work when the TextBox is in a non-active tab

Bisogna focalizzare la casella di testo, aggiornare la posizione del cursore e poi scorrere fino a finire:

Status.Focus(); 
Status.CaretIndex = Status.Text.Length; 
Status.ScrollToEnd(); 

EDIT

Esempio TextBox:

<TextBox TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" 
     AcceptsReturn="True" Name="textBox"/> 
+0

Ho provato questo. Il Caret in effetti si trova dopo l'ultima riga nella casella di testo, ma non si verifica lo scorrimento verso di esso, vedo ancora le righe superiori dopo l'esecuzione dell'applicazione (vedere la parte sinistra dell'immagine nel commento sopra). – Jaded

+1

Ho aggiunto un esempio di casella di testo che sto utilizzando e lo scorrimento funziona. Potrebbe essere necessario aggiungere la proprietà TextWrapping. –

+0

Sembra che il problema sia il fatto che la casella di testo non ha la possibilità di aggiornare/invalidare se stessa quando le operazioni vengono eseguite dopo che l'applicazione è stata caricata (nel costruttore di pagine). Quando inserisco la logica nel gestore di pulsanti e lo eseguo manualmente, lo scorrimento funziona davvero come un incantesimo. * modifica * Loaded + = (sender, args) => TestOperations() in page ctor ha fatto il trucco. Grazie per l'aiuto. L'unica cosa che vorrei sapere quale metodo potrei eseguire manualmente per ottenere lo stesso effetto e lasciare il codice nel costruttore di pagine. – Jaded

2

Grazie! Ho aggiunto questo per ricordare il focus originale:

var oldFocusedElement = FocusManager.GetFocusedElement(this); 

this.textBox.Focus(); 
this.textBox.CaretIndex = this.textBox.Text.Length; 
this.textBox.ScrollToEnd(); 

FocusManager.SetFocusedElement(this, oldFocusedElement); 
12

Se si fanno in un semplice controllo personalizzato allora non è necessario alcun codice dietro a fare lo scorrimento.

public class ScrollingTextBox : TextBox { 

    protected override void OnInitialized (EventArgs e) { 
     base.OnInitialized(e); 
     VerticalScrollBarVisibility = ScrollBarVisibility.Auto; 
     HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; 
    } 

    protected override void OnTextChanged (TextChangedEventArgs e) { 
     base.OnTextChanged(e); 
     CaretIndex = Text.Length; 
     ScrollToEnd(); 
    } 

} 

Se si utilizza WPF, sarebbe molto meglio utilizzare l'associazione anziché passare la casella di testo nel codice sottostante.

+0

+1 Molto più semplice di altri post sullo stesso argomento Ho anche mantenuto solo OnTextChanged (...) {base.OnTextChanged (e); ScrollToEnd();} perché per la mia semplice applicazione era sufficiente . – NGI