如果設置TextWrapping「包裝」,一個WPF的TextBlock可以有幾行文字。 有沒有一種「乾淨」的方式來獲取文本的行數?我考慮看所需的高度,並將其除以每條線的估計高度。但是,這似乎很髒。有沒有更好的辦法?有關WPF可見行數
可見行數
回答
有一件事情是非常好的是,所有的控制都非常無外觀。正因爲如此,我們可以利用TextBox,它有一個LineCount屬性(爲什麼它不是一個DependencyProperty或爲什麼TextBlock不具有它我不知道)。使用TextBox,我們可以簡單地對它進行重新模板化,使其看起來更像TextBlock。在我們自定義的樣式/模板中,我們將把IsEnabled設置爲False,並且創建一個基本的控件重新模板,以便禁用的外觀不再存在。通過使用TemplateBindings,我們還可以綁定任何我們想要維護的屬性,如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到處理LineCount的檢索和設置。我們將使用AttachedProperties來做同樣的事情,但是現在我們可以在任何地方使用它,並通過TextBox而不是Window的DataContext綁定到它。現在
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>
最簡單的方法是LineCount財產。你也有一個叫做GetLastVisibleLineIndex的方法,讓你知道文本框可以顯示多少行(沒有滾動條)。
如果您想知道何時添加一行,您可以在TextChanged事件中聽到並詢問LineCount屬性(您需要將las LineCount保存爲變量以進行比較)。
TextBlock沒有LineCount屬性。這完全是TextBox的領域。 – 2011-02-04 01:14:25
我發現有用的壽。良好的信息,錯誤的答案。 – mdw7326 2014-11-18 13:08:19
// this seems to do the job
<TextBox x:Name="DescriptionTextBox"
Grid.Row="03"
Grid.RowSpan="3"
Grid.Column="01"
Width="100"
AcceptsReturn="True"
MaxLength="100"
MaxLines="3"
PreviewKeyDown="DescriptionTextBox_PreviewKeyDown"
Text="{Binding Path=Description,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
/// <summary>
/// we need to limit a multi line textbox at entry time
/// </summary>
/// <param name="sender">
/// The sender.
/// </param>
/// <param name="e">
/// The e.
/// </param>
private void DescriptionTextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
TextBox thisTextBox = sender as TextBox;
if (thisTextBox != null)
{
// only check if we have passed the MaxLines
if (thisTextBox.LineCount > thisTextBox.MaxLines)
{
// we are going to discard the last entered character
int numChars = thisTextBox.Text.Length;
// force the issue
thisTextBox.Text = thisTextBox.Text.Substring(0, numChars - 1);
// set the cursor back to the last allowable character
thisTextBox.SelectionStart = numChars - 1;
// disallow the key being passed in
e.Handled = true;
}
}
}
我已經看到,這個問題已經7歲了,但我只是一個解決方案來:
TextBlock的有一個叫LineCount的私人財產。我創建了一個擴展方法來讀取此值:
public static class TextBlockExtension
{
public static int GetLineCount(this TextBlock tb)
{
var propertyInfo = GetPrivatePropertyInfo(typeof(TextBlock), "LineCount");
var result = (int)propertyInfo.GetValue(tb);
return result;
}
private static PropertyInfo GetPrivatePropertyInfo(Type type, string propertyName)
{
var props = type.GetProperties(BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic);
return props.FirstOrDefault(propInfo => propInfo.Name == propertyName);
}
}
- 1. StyledText可見行數
- 2. Tableview可見行
- 3. 定義可見行數來實現對可見單元格僅
- 4. SSRS行可見性
- 5. SSRS基於另一行可見性的行可見性
- 6. 當DOM可見時執行jQuery函數
- 7. C#的Excel互操作數可見行
- 8. 計算DataGrid中可見行的數量
- 9. CSV導出可見行
- 10. 最後一行不可見
- 11. 的TableView:調整可見行
- 12. 使可見過濾行
- 13. Slickgrid組行不可見
- 14. MonoTouch.Dialog - 最後一行可見?
- 15. 單個DataGrid行可見性
- 16. SSRS Sum可見父行組
- 17. Html.DropDownListFor使可見/不可見
- 18. 如何使索引在運行時可見/不可見
- 19. 設置JLabel在JButton被單擊時可見可見執行
- 20. 如何在運行時使窗口可見/不可見?
- 21. 使表格行不可見,但其內容可見
- 22. 表td邊框可見和不可見同一行
- 23. 僅刪除可見行的可見副本
- 24. powershell不可見的可執行文件
- 25. 反應原生ListView行可見行
- 26. Datagridview行不可見,行選擇隨機
- 27. 獲取否。 TextView上的可能/可見行數
- 28. tkMessageBox從桌面運行時彈出不可見,從啓動運行時可見
- 29. CSS3奇數行甚至只有可見行
- 30. 不可見的數據
這太好了。 但是,TextBox比TextBlock更有限,因爲它們具有統一的Font系列/字體大小。因此,計算行數很容易。另一方面,TextBlocks可以具有不同高度的內聯。這使事情變得更加困難。 – tom7 2009-07-09 22:33:56