vscrollbar tamaño propiedades programar eventos ejemplo desplazamiento cambiar barra c# .net wpf scrollbar textblock

c# - tamaño - Barra de desplazamiento vertical automático en WPF TextBlock?



textbox c# ejemplo (10)

Tengo un TextBlock en WPF. Le escribo muchas líneas, muy por encima de su altura vertical. Esperaba que una barra de desplazamiento vertical apareciera automáticamente cuando eso sucediera, pero no fue así. Intenté buscar una propiedad de la barra de desplazamiento en el panel Propiedades, pero no pude encontrar una.

¿Cómo puedo hacer una barra de desplazamiento vertical creada automáticamente para mi TextBlock una vez que su contenido exceda su altura?

Aclaración: preferiría hacerlo desde el diseñador y no escribiendo directamente al XAML.


Algo mejor sería:

<Grid Width="Your-specified-value" > <ScrollViewer> <TextBlock Width="Auto" TextWrapping="Wrap" /> </ScrollViewer> </Grid>

Esto asegura que el texto en su bloque de texto no se desborde y se superponga con los elementos debajo del bloque de texto como puede ser el caso si no usa la cuadrícula. Eso me sucedió cuando probé otras soluciones, aunque el bloque de texto ya estaba en una cuadrícula con otros elementos. Tenga en cuenta que el ancho del bloque de texto debe ser Automático y debe especificar el deseado en el elemento Cuadrícula. Hice esto en mi código y funciona muy bien. HTH.


Envuélvelo en un visor de desplazamiento:

<ScrollViewer> <TextBlock /> </ScrollViewer>

NOTA: esta respuesta se aplica a un TextBlock (un elemento de texto de solo lectura) tal como se solicita en la pregunta original.

Si desea mostrar barras de desplazamiento en un TextBox texto (un elemento de texto editable), use las propiedades adjuntas de ScrollViewer :

<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />

Los valores válidos para estas dos propiedades son Disabled , Auto , Hidden y Visible .


Esta es una solución simple para esa pregunta. El desplazamiento vertical se activará solo cuando el texto se desborde.

<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />


Esta respuesta describe una solución utilizando MVVM.

Esta solución es excelente si desea agregar un cuadro de registro a una ventana, que se desplaza automáticamente hacia la parte inferior cada vez que se agrega un nuevo mensaje de registro.

Una vez que se agregan estas propiedades adjuntas, se pueden reutilizar en cualquier lugar, por lo que es un software muy modular y reutilizable.

Añade este XAML:

<TextBox IsReadOnly="True" Foreground="Gainsboro" FontSize="13" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" attachedBehaviors:TextBoxApppendBehaviors.AppendText="{Binding LogBoxViewModel.AttachedPropertyAppend}" attachedBehaviors:TextBoxClearBehavior.TextBoxClear="{Binding LogBoxViewModel.AttachedPropertyClear}" TextWrapping="Wrap">

Añadir esta propiedad adjunta:

public static class TextBoxApppendBehaviors { #region AppendText Attached Property public static readonly DependencyProperty AppendTextProperty = DependencyProperty.RegisterAttached( "AppendText", typeof (string), typeof (TextBoxApppendBehaviors), new UIPropertyMetadata(null, OnAppendTextChanged)); public static string GetAppendText(TextBox textBox) { return (string)textBox.GetValue(AppendTextProperty); } public static void SetAppendText( TextBox textBox, string value) { textBox.SetValue(AppendTextProperty, value); } private static void OnAppendTextChanged( DependencyObject d, DependencyPropertyChangedEventArgs args) { if (args.NewValue == null) { return; } string toAppend = args.NewValue.ToString(); if (toAppend == "") { return; } TextBox textBox = d as TextBox; textBox?.AppendText(toAppend); textBox?.ScrollToEnd(); } #endregion }

Y esta propiedad adjunta (para borrar la caja):

public static class TextBoxClearBehavior { public static readonly DependencyProperty TextBoxClearProperty = DependencyProperty.RegisterAttached( "TextBoxClear", typeof(bool), typeof(TextBoxClearBehavior), new UIPropertyMetadata(false, OnTextBoxClearPropertyChanged)); public static bool GetTextBoxClear(DependencyObject obj) { return (bool)obj.GetValue(TextBoxClearProperty); } public static void SetTextBoxClear(DependencyObject obj, bool value) { obj.SetValue(TextBoxClearProperty, value); } private static void OnTextBoxClearPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs args) { if ((bool)args.NewValue == false) { return; } var textBox = (TextBox)d; textBox?.Clear(); } }

Luego, si está utilizando un marco de inyección de dependencias como MEF, puede colocar todo el código específico de registro en su propio ViewModel:

public interface ILogBoxViewModel { void CmdAppend(string toAppend); void CmdClear(); bool AttachedPropertyClear { get; set; } string AttachedPropertyAppend { get; set; } } [Export(typeof(ILogBoxViewModel))] public class LogBoxViewModel : ILogBoxViewModel, INotifyPropertyChanged { private readonly ILog _log = LogManager.GetLogger<LogBoxViewModel>(); private bool _attachedPropertyClear; private string _attachedPropertyAppend; public void CmdAppend(string toAppend) { string toLog = $"{DateTime.Now:HH:mm:ss} - {toAppend}/n"; // Attached properties only fire on a change. This means it will still work if we publish the same message twice. AttachedPropertyAppend = ""; AttachedPropertyAppend = toLog; _log.Info($"Appended to log box: {toAppend}."); } public void CmdClear() { AttachedPropertyClear = false; AttachedPropertyClear = true; _log.Info($"Cleared the GUI log box."); } public bool AttachedPropertyClear { get { return _attachedPropertyClear; } set { _attachedPropertyClear = value; OnPropertyChanged(); } } public string AttachedPropertyAppend { get { return _attachedPropertyAppend; } set { _attachedPropertyAppend = value; OnPropertyChanged(); } } #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion }

Así es como funciona:

  • El ViewModel alterna las propiedades adjuntas para controlar el TextBox.
  • Como está usando "Append", es muy rápido.
  • Cualquier otro ViewModel puede generar mensajes de registro llamando a los métodos en el registro de ViewModel.
  • A medida que usamos el ScrollViewer integrado en el TextBox, podemos hacer que se desplace automáticamente a la parte inferior del cuadro de texto cada vez que se agregue un nuevo mensaje.

No sé si alguien más tiene este problema pero envolviendo mi TextBlock en un ScrollViewer alguna manera desordenado mi UI - como una solución simple, descubrí que reemplazar el TextBlock por un TextBox como este

<TextBox Name="textBlock" SelectionBrush="Transparent" Cursor="Arrow" IsReadOnly="True" Text="My Text" VerticalScrollBarVisibility="Auto">

crea un TextBox que se ve y se comporta como un TextBlock con una barra de desplazamiento (y puedes hacerlo todo en el diseñador).


Puede usar lo siguiente ahora:

<TextBox Name="myTextBox" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">SOME TEXT </TextBox>



Traté de hacer que estas sugerencias funcionaran para un bloque de texto, pero no pude hacer que funcionara. Incluso intenté que funcionara desde el diseñador. (Mire en Diseño y expanda la lista haciendo clic en la flecha hacia abajo "V" en la parte inferior) Intenté configurar el visor de desplazamiento en Visible y luego en Automático , pero aún así no funcionaría.

Finalmente me di por vencido y cambié el TextBlock a un TextBox con el conjunto de atributos Readonly , y funcionó como un encanto.


<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto"> <TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" /> </ScrollViewer>

Esta es la forma de usar el TextBox de desplazamiento en XAML y usarlo como área de texto.


<ScrollViewer MaxHeight="50" Width="Auto" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <TextBlock Text="{Binding Path=}" Style="{StaticResource TextStyle_Data}" TextWrapping="Wrap" /> </ScrollViewer>

Estoy haciendo esto de otra manera al poner MaxHeight en ScrollViewer.

Solo ajusta MaxHeight para mostrar más o menos líneas de texto. Fácil.