我在WPF中有一个TextBlock
,我写了很多行文字,超出了它的垂直高度。我期望当这种情况发生时,竖直滚动条会自动出现,但实际上没有出现。我尝试在属性窗格中查找滚动条属性,但未能找到。
如何使我的TextBlock
在其内容超过其高度时自动创建垂直滚动条?
澄清一下:我更愿意通过设计器完成而不是直接编写XAML。
将其包装在滚动查看器中:
<ScrollViewer>
<TextBlock />
</ScrollViewer>
注意:本答案适用于原问题中所要求的TextBlock
(只读文本元素)。
如果您想在TextBox
(可编辑文本元素)中显示滚动条,则可以使用ScrollViewer
附加属性:
<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
这两个属性的有效值包括Disabled
、Auto
、Hidden
和Visible
。
现在可以使用以下代码:
<TextBox Name="myTextBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True">SOME TEXT
</TextBox>
TextBlock
而不是TextBox
的(如标题和开头所述),但第二段提到了TextBox
。为了明确,这个答案绝对是处理文本框的最佳方法,而我知道的最佳处理文本块的方法则是我的答案 :) - Drew Noakes更好的方式是:
<Grid Width="Your-specified-value" >
<ScrollViewer>
<TextBlock Width="Auto" TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
使用网格可以确保文本块中的文本不会溢出并重叠在文本块下面的元素上,因为如果您不使用网格,则可能会发生这种情况。当我尝试其他解决方案时,即使文本块已经在带有其他元素的网格中,这种情况也发生了。请记住,文本块的宽度应该是自动的,并且您应该在网格元素中指定所需的宽度。我在我的代码中这样做,效果非常好。HTH。
<ScrollViewer MaxHeight="50"
Width="Auto"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="{Binding Path=}"
Style="{StaticResource TextStyle_Data}"
TextWrapping="Wrap" />
</ScrollViewer>
我通过在ScrollViewer中设置MaxHeight的方式以另一种方式来实现这一点。
只需调整MaxHeight即可显示更多或更少的文本行。非常容易。
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" />
</ScrollViewer>
TextBlock
有关,而不是 TextBox
。 - Afzaal Ahmad Zeeshan不知道是否有其他人遇到过这个问题,将我的TextBlock
包装成一个ScrollViewer
会在某种程度上破坏我的UI - 作为一个简单的解决方法,我发现将TextBlock
替换为像这样的TextBox
<TextBox SelectionBrush="Transparent"
Cursor="Arrow"
IsReadOnly="True"
Text="{Binding Text}"
VerticalScrollBarVisibility="Auto">
以下答案描述了使用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
}
您可以使用
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
TextBlock
更改为具有只读属性集的TextBox
,它就像魔法般地工作了。
TextBlock
而不是TextBox
的。 - Drew Noakes