2012-01-20 22 views
34

Hay muchas preguntas similares sobre Internet, incluidas SO, pero las soluciones propuestas no funcionan en mi caso. Escenario: hay un cuadro de texto de registro en xamlCuadro de texto de líneas múltiples con desplazamiento vertical automático

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

hay métodos de código subyacente que hacer algún trabajo y añadir un poco de líneas múltiples (tal vez ese es el problema?) Mensajes en el campo respectivo:

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 
} 

Necesita desplazarse a la parte inferior del cuadro de texto después de que se lleven a cabo todas las acciones. Probé ScrollToEnd(), ScrollToLine, envolviendo textbox en ScrollViewer, Selection y Caret workarounds, adjuntando ScrollToEnd a TextChanged. Nada de esto funciona, después de que las líneas de ejecución que desbordan la altura del cuadro de texto todavía tienen que desplazarse manualmente. Perdón por la pregunta duplicada, creo que me faltan algunos problemas menores que pueden ser resueltos rápidamente por alguien que tenga una nueva visión del problema. Gracias por adelantado.

+0

Cuando dice que necesita "desplazarse hasta [la] parte inferior de [los] texto", ¿realmente quiere decir "desplazarse" como en "el último texto anexado es completamente visible"? ¿O quieres que el cursor esté al final del cuadro de texto? –

+0

Primero. Para ilustrar hice una captura de pantalla: a la izquierda está lo que obtengo, a la derecha es lo que necesito (como desplazamiento manual hacia abajo): http://i.piccy.info/i7/0c105234c75b7031df050587f72771b4/1-5-3848/56682026/120120114019_6.jpg – Jaded

Respuesta

73

De acuerdo con esta pregunta: TextBox.ScrollToEnd doesn't work when the TextBox is in a non-active tab

Usted tiene que centrarse el cuadro de texto, actualizar la posición de intercalación y luego desplazarse a fin:

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

EDITAR

Ejemplo Cuadro de texto:

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

Intenté eso. Caret de hecho está después de la última línea en el cuadro de texto, pero no se puede desplazar hasta allí, aún veo las líneas superiores después de ejecutar la aplicación (ver la parte izquierda de la imagen en el comentario anterior). – Jaded

+1

He agregado un ejemplo de cuadro de texto que estoy usando y funciona el desplazamiento. Es posible que deba agregar la propiedad TextWrapping. –

+0

Parece que el problema es el hecho de que el cuadro de texto no tiene la posibilidad de actualizarse/invalidarse cuando las operaciones se ejecutan después de cargar la aplicación (en el constructor de página). Cuando pongo la lógica en el controlador de botón y lo ejecuto manualmente, el desplazamiento funciona realmente como un amuleto. * edit * Loaded + = (sender, args) => TestOperations() en la página ctor hizo el truco. Gracias por la ayuda. Lo único que me gustaría saber es qué método podría ejecutar manualmente para lograr el mismo efecto y aún así dejar el código en el constructor de la página. – Jaded

2

¡Gracias! He añadido este para recordar el enfoque original:

var oldFocusedElement = FocusManager.GetFocusedElement(this); 

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

FocusManager.SetFocusedElement(this, oldFocusedElement); 
12

Si usted lo hace en un simple control personalizado a continuación, no es necesario ningún código detrás para hacer el movimiento en sentido vertical.

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(); 
    } 

} 

Si está utilizando WPF sería mucho mejor usar la unión en lugar de pasar el cuadro de texto alrededor en el código subyacente.

+0

+1 Mucho más simple que otras publicaciones sobre el mismo tema Incluso mantuve OnTextChanged (...) {base.OnTextChanged (e); ScrollToEnd();} porque para mi simple aplicación era suficiente . – NGI

Cuestiones relacionadas