[英]How to create multiline textbox which shows apostrophe before each line
我想要一個多行文本框,該文本框在每行之前和之后顯示撇號。 這樣文本框看起來像:
" Hello this "
" is a funny "
" string test "
或者例如:
// This is
// a muliline
// comment.
編輯:這些特殊字符必須是只讀的,如果從文本框中的用戶復制文本這些字符不應該被包括在內。
使用兩個彼此直接放置的文本框,這非常容易。 后面的是一個普通的文本框,帶有額外的填充和透明文本。 前一個有您的多余字符,但邊框已隱藏,並且IsHitTestVisible=False
和Focusable=False
因此它不會與用戶交互。 用戶只與后文本框交互,而前文本框是顯示文本的文本框。 與值轉換器的綁定使前文本框准確顯示后文本框顯示的內容,以及額外的字符。
它是這樣的:
<ControlTemplate x:Key="TextBoxWithExtraCharacters" TargetType="{x:Type TextBox}">
<ControlTemplate.Resources>
<!-- Remove the border from the inner textboxes -->
<ControlTemplate TargetType="{x:Type TextBox}">
<Decorator x:Name="PART_Content" />
</ControlTemplate>
</ControlTemplate.Resources>
<!-- Now add our own border -->
<Border
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<!-- Scrolling must happen at this level so both text boxes scroll simultaneously -->
<ScrollViewer>
<Grid>
<!-- Rear textbox provides editing and user interaction but the text is transparent -->
<TextBox
Margin="10,0,10,0"
Foreground="Transparent"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}"
Background="{x:Null}"
IsReadOnly="{TemplateBinding IsReadOnly}"
IsUndoEnabled="{TemplateBinding IsUndoEnabled}"
AcceptsReturn="{TemplateBinding AcceptsReturn}"
AcceptsTab="{TemplateBinding AcceptsTab}"
/>
<!-- Front textbox displays modified text but does not interact with user -->
<TextBox
IsHitTestVisible="false"
Focusable="false"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent},
Converter={x:Static ExtraCharacterConverter.Instance}"
Background="{x:Null}"
IsReadOnly="{TemplateBinding IsReadOnly}"
IsUndoEnabled="{TemplateBinding IsUndoEnabled}"
AcceptsReturn="{TemplateBinding AcceptsReturn}"
AcceptsTab="{TemplateBinding AcceptsTab}"
/>
</Grid>
</ScrollViewer>
</Border>
</ControlTemplate>
ExtraCharacterConverter是一個簡單的IValueConverter
類,該類通過獲取給定的字符串,在其后加上引號或//或其他內容並返回結果來實現Convert
方法。
請注意,我在后文本框上硬編碼了10個單位的左右邊距,假定引號字符的寬度是特定的。 這應該恰好是所添加字符的寬度,以使文本正確對齊。 您想得到正確的選擇,否則插入符號和文本選擇的位置將是錯誤的。 還要注意,隨着字體大小和其他字符的選擇,正確的值也會改變。
硬編碼裕度的一個簡單替代方法是將其設置為FontSize, FontFamily, FontWeight
等的多重綁定,然后使用IMultiValueConverter
來給定這些值來計算適當的裕度。
注意:當涉及到用於文本選擇的配色方案時,此解決方案絕對不能令人滿意。 此問題可以解決,但需要更復雜的解決方案:后面的文本框相同,但其文本不可見。 前面的文本框替換為RichTextBox(或TextBlock),其內容被動態計算為帶有額外字符的文本,但常規文本透明。 因為它是RichTextBox,所以可以看到其他字符,而其他字符是透明的。
您是否不能簡單地使用multiline屬性設置為true的繼承來創建用戶定義的文本框,並在文本更改事件上使用一些特殊代碼來檢查每行的第一個和最后一個索引,以確保該行上有撇號? 或者,如果沒有辦法迭代行,您是否可以只在每個chr(11)或chr(13)之前和之后觀看字符?
對於winforms,這並不困難,但是我不確定WPF。
~~~~~~~~~~~~~~~~~~~~~~~~編輯1:1/25/2009 9:12 AM CT ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
如果您希望用戶不能對其進行編輯或使引號混亂,則可以在KeyPressed事件處理程序中編寫特定的代碼(如果正在執行繼承的控件,則可以重寫OnKeyPressed函數),以防止它們在之前或之后添加字符。在chr(11)或chr(13)之后,如果他們試圖刪除它並取消無效的擊鍵,請立即將其重新添加。
我在VB .NET中為錢文本框字段編寫了與此類似的代碼。 它可以幫助您了解我在說什么,也可以幫助您進行操作:
Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.MouseEventArgs)
If Me.SelectionStart = 0 Then
Me.SelectionStart = Me.Text.Length
End If
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
If Not Me.Text.IndexOf("$") = 0 Then
Me.Text = "$" + Me.Text.Replace("$", "")
End If
If Me.SelectionStart = 0 Then
Me.SelectionStart = Me.Text.Length
End If
End Sub
Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If NOT ((Char.IsDigit(e.KeyChar) Or (e.KeyChar = CChar(".") And Not Me.Text.Contains(".")) Or Char.IsControl(e.KeyChar)) And (Not Char.IsDigit(e.KeyChar) Or (Me.SelectionStart <= Me.Text.IndexOf(".") + 2 Or Me.Text.IndexOf(".") = -1))) Then
e.Handled = True
End If
End Sub
我想說,最好的選擇是實現自己的文本框(從文本框本身繼承而來,因此您可以免費獲得所有功能),並覆蓋繪圖代碼並自己寫出每一行(在輸入之前/之后添加)在寫出每一行時都用單引號引起來)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.