Автоматическая вертикальная полоса прокрутки в WPF TextBlock?
У меня есть TextBlock
в WPF. Я пишу много строк, намного превышающих его вертикальную высоту. Я ожидал, что вертикальная полоса прокрутки появится автоматически, когда это произойдет, но это не так. Я попытался найти свойство полосы прокрутки на панели "Свойства", но не смог найти его.
Как создать вертикальную полосу прокрутки, созданную автоматически для моего TextBlock
, когда ее содержимое превысит ее высоту?
Уточнение: я предпочел бы сделать это от дизайнера, а не напрямую писать в XAML.
Ответы
Ответ 1
Оберните его в средстве просмотра прокрутки:
<ScrollViewer>
<TextBlock />
</ScrollViewer>
ПРИМЕЧАНИЕ этот ответ относится к TextBlock
(текстовому элементу только для чтения), как задано в исходном вопросе.
Если вы хотите показывать полосы прокрутки в TextBox
(редактируемый текстовый элемент), используйте свойства ScrollViewer
:
<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
Допустимыми значениями для этих двух свойств являются Disabled
, Auto
, Hidden
и Visible
.
Ответ 2
может использовать следующее:
<TextBox Name="myTextBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True">SOME TEXT
</TextBox>
Ответ 3
Что-то лучше было бы:
<Grid Width="Your-specified-value" >
<ScrollViewer>
<TextBlock Width="Auto" TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
Это гарантирует, что текст в вашем текстовом блоке не будет переполняться и перекрывать элементы под текстовым блоком, как это может быть, если вы не используете сетку. Это случилось со мной, когда я пробовал другие решения, хотя текстовый блок уже был в сетке с другими элементами. Имейте в виду, что ширина текстового блока должна быть автоматической, и вы должны указать желаемый элемент в элементе Grid. Я сделал это в своем коде, и он работает красиво.
НТН.
Ответ 4
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" />
</ScrollViewer>
Это способ использовать прокрутку TextBox в XAML и использовать его как текстовую область.
Ответ 5
В этом ответе описывается решение с использованием MVVM.
Это решение отлично подходит, если вы хотите добавить окно журнала в окно, которое автоматически прокручивается вниз каждый раз, когда добавляется новое сообщение регистрации.
После добавления этих добавленных свойств они могут быть повторно использованы в любом месте, поэтому он делает очень модульное и многоразовое программное обеспечение.
Добавьте этот 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">
Добавьте это прикрепленное свойство:
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
}
И это прикрепленное свойство (чтобы снять ящик):
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();
}
}
Затем, если вы используете инфраструктуру инъекций зависимостей, такую как MEF, вы можете поместить весь код для ведения журнала в свой собственный 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
}
Вот как это работает:
- ViewModel переключает прикрепленные свойства для управления TextBox.
- Как он использует "Добавить", он молниеносно.
- Любой другой ViewModel может генерировать сообщения журнала, вызывая методы в журнале ViewModel.
- Поскольку мы используем ScrollViewer, встроенный в TextBox, мы можем автоматически прокручивать его до нижней части текстового поля каждый раз при добавлении нового сообщения.
Ответ 6
Вы можете использовать
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Это прикрепленное свойство wpf.
Для получения дополнительной информации
http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html
Ответ 7
<ScrollViewer MaxHeight="50"
Width="Auto"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="{Binding Path=}"
Style="{StaticResource TextStyle_Data}"
TextWrapping="Wrap" />
</ScrollViewer>
Я делаю это по-другому, помещая MaxHeight в ScrollViewer.
Просто настройте MaxHeight, чтобы показать больше или меньше строк текста. Легко.