我在WPF中有一个TextBlock
。我写了很多行,远远超过它的垂直高度。我预计一个垂直滚动条会在发生时自动出现,但事实并非如此。我试图在“属性”窗格中查找滚动条属性,但找不到。
如果我的TextBlock
内容超出其高度,我该如何自动创建垂直滚动条?
澄清:我宁愿从设计师那里做,而不是直接写给XAML。
答案 0 :(得分:517)
将其包裹在滚动查看器中:
<ScrollViewer>
<TextBlock />
</ScrollViewer>
注意此答案适用于原始问题中要求的TextBlock
(只读文字元素)。
如果要在TextBox
(可编辑的文本元素)中显示滚动条,请使用ScrollViewer
附加属性:
<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
这两个属性的有效值为Disabled
,Auto
,Hidden
和Visible
。
答案 1 :(得分:98)
现在可以使用以下内容:
<TextBox Name="myTextBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True">SOME TEXT
</TextBox>
答案 2 :(得分:19)
更好的是:
<Grid Width="Your-specified-value" >
<ScrollViewer>
<TextBlock Width="Auto" TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
这可确保文本块中的文本不会溢出并与文本块下方的元素重叠,如果您不使用网格的话。当我尝试其他解决方案时,即使文本块已经在其他元素的网格中,这也发生在我身上。请记住,文本块的宽度应为“自动”,您应在Grid元素中指定所需的宽度。我在我的代码中做到了这一点并且工作得非常好。 HTH。
答案 3 :(得分:5)
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" />
</ScrollViewer>
这是在XAML中使用滚动TextBox并将其用作文本区域的方法。
答案 4 :(得分:3)
这个答案描述了使用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
}
以下是它的工作原理:
答案 5 :(得分:3)
<ScrollViewer MaxHeight="50"
Width="Auto"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="{Binding Path=}"
Style="{StaticResource TextStyle_Data}"
TextWrapping="Wrap" />
</ScrollViewer>
我通过将MaxHeight放在ScrollViewer中以另一种方式执行此操作。
只需调整MaxHeight即可显示更多或更少的文本行。容易。
答案 6 :(得分:2)
您可以使用
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
这些是wpf的附加属性。 有关更多信息
http://wpfbugs.blogspot.in/2014/02/wpf-layout-controls-scrollviewer.html
答案 7 :(得分:1)
我试图使这些建议适用于文本块,但无法使其起作用。我什至试图让设计师使用它。 (在“布局”中,通过单击底部的向下箭头“ V”展开列表),我尝试将滚动查看器设置为 Visible ,然后设置为 Auto ,但仍然不会不行
我最终放弃了,将TextBlock
更改为TextBox
,并设置了 只读 属性,它像一个魅力一样工作。
答案 8 :(得分:0)
不知道是否有其他人遇到此问题,但将我的TextBlock
包裹在ScrollViewer
某些人的网页上,这是一个简单的解决方法,我发现将TextBlock
替换为{ {1}}喜欢这个
TextBox
创建一个<TextBox Name="textBlock" SelectionBrush="Transparent" Cursor="Arrow" IsReadOnly="True" Text="My Text" VerticalScrollBarVisibility="Auto">
,其外观和行为类似于带有滚动条的TextBox
(您可以在设计器中完成所有操作)。
答案 9 :(得分:0)
这是一个简单的解决方案。仅当文本溢出时,才会激活垂直滚动。
<TextBox Text="Try typing some text here " ScrollViewer.VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow" />