C# 影响各行的Wpf多行文本框样式
我需要制作一个多行文本框,当行超过80个字符时,它会改变字符的背景。因此,如果有人键入一个85个字符的句子,最后5个字符的背景将为黄色。我希望它将此功能作为样式的一部分,因为目前我们正在使用代码中的逻辑来执行此操作,当有人快速键入时,它会滞后 当前突出显示imlpC# 影响各行的Wpf多行文本框样式,c#,wpf,xaml,textbox,styles,C#,Wpf,Xaml,Textbox,Styles,我需要制作一个多行文本框,当行超过80个字符时,它会改变字符的背景。因此,如果有人键入一个85个字符的句子,最后5个字符的背景将为黄色。我希望它将此功能作为样式的一部分,因为目前我们正在使用代码中的逻辑来执行此操作,当有人快速键入时,它会滞后 当前突出显示imlp private void HighlightLines() { try { //// x is the distance in the
private void HighlightLines()
{
try
{
//// x is the distance in the row from the left side of the Textbox. e.g. Each character is one unit.
int x = 0;
//// y is the distance in the columns from the top of the Textbox. e.g. Each character is one unit.
int y = 0;
//// lines is the number of newline characters found in the Text.
int lines = 0;
//// Point 1 is the starting point of the range that needs to be highlighted.
TextPointer point1 = this.Document.ContentStart;
//// Point 2 is the end point of the range that needs to be highlighted.
TextPointer point2 = this.Document.ContentStart;
//// Range is the distance from Point 1 to Point 2 needed to apply the Yellow color to the area past 69 characters.
TextRange range;
//// Additional Ranges is the collection of all the ranges that need to be Yellow.
this.AdditionalRanges = new ObservableCollection<TextRange>();
//// Count the number of lines.
for (int i = 0; i < this.Text.Length; i++)
{
if (this.Text[i] == '\n')
{
lines++;
this.AdditionalRanges.Add(new TextRange(this.Document.ContentStart, this.Document.ContentEnd));
}
}
//// This map is used to differentiate which lines need to be colored. (True means the range is over 69 characters. False means the opposite).
bool[] map = new bool[lines];
//// Traverse the whole text.
for (int i = 0; i < this.Text.Length; i++)
{
var currentCharacter = this.Text[i];
var newLineCharacter = '\n';
if (currentCharacter == newLineCharacter)
{
var pointDifference = point1.GetOffsetToPosition(point2);
point1 = point1.GetPositionAtOffset(pointDifference);
x = 0;
y++;
}
else if (x > 69)
{
range = new TextRange(point1, point2);
this.AdditionalRanges[y] = range;
map[y] = true;
if (point2.GetNextInsertionPosition(LogicalDirection.Forward) != null)
{
point2 = point2.GetNextInsertionPosition(LogicalDirection.Forward);
}
}
else if (point1.GetNextInsertionPosition(LogicalDirection.Forward) != null && point2.GetNextInsertionPosition(LogicalDirection.Forward) != null)
{
point1 = point1.GetNextInsertionPosition(LogicalDirection.Forward);
point2 = point2.GetNextInsertionPosition(LogicalDirection.Forward);
x++;
}
}
//// Make everything white.
foreach (var item in this.AdditionalRanges)
{
item.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.White);
}
//// Make the appropriate ranges Yellow.
for (int i = 0; i < this.AdditionalRanges.Count; i++)
{
if (map[i])
{
this.AdditionalRanges[i].ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
}
}
}
catch (Exception e)
{
// drop exception. this has only broke once and we dont exactly know why.
}
}
private void HighlightLines()
{
尝试
{
////x是行中距文本框左侧的距离。例如,每个字符为一个单位。
int x=0;
////y是列中距文本框顶部的距离。例如,每个字符为一个单位。
int y=0;
////lines是在文本中找到的换行符数。
int行=0;
////点1是需要高亮显示的范围的起点。
TextPointer point1=this.Document.ContentStart;
////点2是需要高亮显示的范围的终点。
TextPointer point2=this.Document.ContentStart;
////范围是将黄色应用于超过69个字符的区域所需的从点1到点2的距离。
文本范围;
////附加范围是需要为黄色的所有范围的集合。
this.AdditionalRanges=新的ObservableCollection();
////数一数行数。
for(int i=0;i69),则为else
{
范围=新文本范围(点1,点2);
这个。附加范围[y]=范围;
map[y]=真;
if(点2.GetNextInsertionPosition(LogicalDirection.Forward)!=null)
{
点2=点2.GetNextInsertionPosition(LogicalDirection.Forward);
}
}
else if(point1.GetNextInsertionPosition(LogicalDirection.Forward)!=null和&point2.GetNextInsertionPosition(LogicalDirection.Forward)!=null)
{
point1=point1.GetNextInsertionPosition(LogicalDirection.Forward);
点2=点2.GetNextInsertionPosition(LogicalDirection.Forward);
x++;
}
}
////把一切都变成白色。
foreach(此.AdditionalRanges中的var项)
{
item.ApplyPropertyValue(TextElement.BackgroundProperty,Bruss.White);
}
////将适当的范围设为黄色。
对于(int i=0;i
它可能是滞后的,因为您的HighlightLines()
方法每次都扫描整个文档,我假设每次按键后都会调用它。理想情况下,您只希望重新扫描已更改的文本部分。幸运的是,TextChanged事件提供了更改的精确偏移量
下面的示例代码是为使用RichTextBox编写的,但您应该能够对其进行调整。此外,您的代码似乎在检查69个字符而不是80个字符,因此这是相同的:
RichTextBox txt;
...
bool suppressChanges = false;
private void Txt_TextChanged(object sender, TextChangedEventArgs e)
{
if (!suppressChanges)
{
// suppress changes because changing highlights will trigger the event again
suppressChanges = true;
foreach (var change in e.Changes)
{
var changeStart = txt.Document.ContentStart.GetPositionAtOffset(change.Offset);
TextRange changedRange;
if (change.AddedLength > 0)
changedRange = new TextRange(changeStart, changeStart.GetPositionAtOffset(change.AddedLength));
else
changedRange = new TextRange(changeStart, changeStart);
SetRangeColors(changedRange);
}
//unsuppress changes
suppressChanges = false;
}
}
void SetRangeColors(TextRange range)
{
// Scan one line at a time starting with the beginning of the range
TextPointer current = range.Start.GetLineStartPosition(0);
while (current != null && current.CompareTo(range.End) < 0)
{
// find the next line or the end of the document
var nextLine = current.GetLineStartPosition(1, out int lines);
TextPointer lineEnd;
if (lines > 0)
lineEnd = nextLine.GetNextInsertionPosition(LogicalDirection.Backward);
else
lineEnd = txt.Document.ContentEnd;
var lineRange = new TextRange(current, lineEnd);
// clear properties first or the offsets won't match the characters
lineRange.ClearAllProperties();
var lineText = lineRange.Text;
if (lineText.Length > 69)
{
var highlight = new TextRange(current.GetPositionAtOffset(70), lineEnd);
highlight.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
}
// advance to the next line
current = lineEnd.GetLineStartPosition(1);
}
}
RichTextBox-txt;
...
bool suppressChanges=false;
私有void Txt_TextChanged(对象发送方,textchangedventargs e)
{
如果(!suppressChanges)
{
//抑制更改,因为更改高光将再次触发事件
suppressChanges=true;
foreach(e.Changes中的var变化)
{
var changeStart=txt.Document.ContentStart.GetPositionAtOffset(change.Offset);
文本范围变化范围;
如果(更改.AddedLength>0)
changedRange=新的文本范围(changeStart,changeStart.GetPositionAtOffset(change.AddedLength));
其他的
changedRange=新文本范围(changeStart,changeStart);
设置范围颜色(更改范围);
}
//取消抑制更改
suppressChanges=false;
}
}
无效设置范围颜色(文本范围)
{
//从范围开始,一次扫描一行
text指针电流=range.Start.GetLineStartPosition(0);
whil