C# 影响各行的Wpf多行文本框样式

C# 影响各行的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

我需要制作一个多行文本框,当行超过80个字符时,它会改变字符的背景。因此,如果有人键入一个85个字符的句子,最后5个字符的背景将为黄色。我希望它将此功能作为样式的一部分,因为目前我们正在使用代码中的逻辑来执行此操作,当有人快速键入时,它会滞后

当前突出显示imlp

 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