gpt4 book ai didi

wpf - TextBlock 的可见行数

转载 作者:行者123 更新时间:2023-12-04 07:14:32 25 4
gpt4 key购买 nike

如果将 TextWrapping 设置为“Wrap”,则 WPF TextBlock 可以包含多行文本。
是否有一种“干净”的方式来获取文本行数?我考虑查看所需的高度并将其除以每条线的估计高度。然而,这似乎很肮脏。有没有更好的办法?

最佳答案

关于 WPF 的一件非常好的事情是所有的控件都非常不美观。因此,我们可以使用 TextBox ,它有一个 LineCount 属性(为什么它不是一个 DependencyProperty 或者为什么 TextBlock 也没有它我不知道)。使用 TextBox,我们可以简单地对其进行重新模板化,使其表现得更像一个 TextBlock。在我们的自定义样式/模板中,我们将 IsEnabled 设置为 False,并且只需创建控件的基本重新模板,以便不再存在禁用的外观。我们还可以通过使用 TemplateBindings 来绑定(bind)我们想要维护的任何属性,例如 Background。

<Style x:Key="Local_TextBox"
TargetType="{x:Type TextBoxBase}">
<Setter Property="IsEnabled"
Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border"
Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

现在,这将使我们的 TextBox 看起来和表现得像一个 TextBlock,但是我们如何获得行数呢?

好吧,如果我们想直接在后面的代码中访问它,那么我们可以注册到 TextBox 的 SizeChanged 事件。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

LongText = "This is a long line that has lots of text in it. Because it is a long line, if a TextBlock's TextWrapping property is set to wrap then the text will wrap onto new lines. However, we can also use wrapping on a TextBox, that has some diffrent properties availible and then re-template it to look just like a TextBlock!";

uiTextBox.SizeChanged += new SizeChangedEventHandler(uiTextBox_SizeChanged);

this.DataContext = this;
}

void uiTextBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
Lines = uiTextBox.LineCount;
}

public string LongText { get; set; }

public int Lines
{
get { return (int)GetValue(LinesProperty); }
set { SetValue(LinesProperty, value); }
}

// Using a DependencyProperty as the backing store for Lines. This enables animation, styling, binding, etc...
public static readonly DependencyProperty LinesProperty =
DependencyProperty.Register("Lines", typeof(int), typeof(MainWindow), new UIPropertyMetadata(-1));
}

但是,由于我倾向于在当前窗口以外的地方使用类似的属性,和/或正在使用 MVVM 并且不想采用这种方法,因此我们可以创建一些 AttachedProperties 来处理检索和设置行数。我们将使用 AttachedProperties 来做同样的事情,但现在我们可以在任何地方将它与任何 TextBox 一起使用,并通过该 TextBox 而不是 Window 的 DataContext 绑定(bind)到它。
public class AttachedProperties
{
#region BindableLineCount AttachedProperty
public static int GetBindableLineCount(DependencyObject obj)
{
return (int)obj.GetValue(BindableLineCountProperty);
}

public static void SetBindableLineCount(DependencyObject obj, int value)
{
obj.SetValue(BindableLineCountProperty, value);
}

// Using a DependencyProperty as the backing store for BindableLineCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BindableLineCountProperty =
DependencyProperty.RegisterAttached(
"BindableLineCount",
typeof(int),
typeof(MainWindow),
new UIPropertyMetadata(-1));

#endregion // BindableLineCount AttachedProperty

#region HasBindableLineCount AttachedProperty
public static bool GetHasBindableLineCount(DependencyObject obj)
{
return (bool)obj.GetValue(HasBindableLineCountProperty);
}

public static void SetHasBindableLineCount(DependencyObject obj, bool value)
{
obj.SetValue(HasBindableLineCountProperty, value);
}

// Using a DependencyProperty as the backing store for HasBindableLineCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HasBindableLineCountProperty =
DependencyProperty.RegisterAttached(
"HasBindableLineCount",
typeof(bool),
typeof(MainWindow),
new UIPropertyMetadata(
false,
new PropertyChangedCallback(OnHasBindableLineCountChanged)));

private static void OnHasBindableLineCountChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var textBox = (TextBox)o;
if ((e.NewValue as bool?) == true)
{
textBox.SetValue(BindableLineCountProperty, textBox.LineCount);
textBox.SizeChanged += new SizeChangedEventHandler(box_SizeChanged);
}
else
{
textBox.SizeChanged -= new SizeChangedEventHandler(box_SizeChanged);
}
}

static void box_SizeChanged(object sender, SizeChangedEventArgs e)
{
var textBox = (TextBox)sender;
(textBox).SetValue(BindableLineCountProperty, (textBox).LineCount);
}
#endregion // HasBindableLineCount AttachedProperty
}

现在,很容易找到 LineCount:
<StackPanel>
<TextBox x:Name="uiTextBox"
TextWrapping="Wrap"
local:AttachedProperties.HasBindableLineCount="True"
Text="{Binding LongText}"
Style="{StaticResource Local_TextBox}" />

<TextBlock Text="{Binding Lines, StringFormat=Binding through the code behind: {0}}" />
<TextBlock Text="{Binding ElementName=uiTextBox, Path=(local:AttachedProperties.BindableLineCount), StringFormat=Binding through AttachedProperties: {0}}" />
</StackPanel>

关于wpf - TextBlock 的可见行数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1105982/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com