英文:
FastColoredTextBox: How add large text - similar to StringBuilder but using styles - and without building undo history
问题
FastColoredTextBox (FCTB) does provide StringBuilder-like methods, for example there is
public virtual void AppendText(string text, Style style)
and similar methods. However, it treats each of these as user input: each action is added to the undo history.
I am building my text programmatically, it is data fields and text, along with all the formatting and styles, and it gets large. At the end I throw away that undo history (or set the control to read only). A lot is wasted in memory and computation time. It takes a few seconds before the control is usable.
So is there a way to build my text before passing it to the FCTB?
英文:
FastColoredTextBox (FCTB) does provide StringBuilder-like methods, for example there is
> public virtual void AppendText(string text, Style style)
and similar methods. However, it treats each of these as user input: each action is added to the undo history.
I am building my text programmatically, it is data fields and text, along with all the formatting and styles, and it gets large. At the end I throw away that undo history (or set the control to read only). A lot is wasted in memory and computation time. It takes a few seconds before the control is usable.
So is there a way to build my text before passing it to the FCTB?
答案1
得分: 0
创建一个派生自TextSource
的类:
public class TextBuilder : TextSource
{
public Line CurrentLine { get; private set; }
public TextBuilder(FastColoredTextBox t) : base(t)
{
AppendLine();
}
public void Append(string text, StyleIndex style = StyleIndex.None)
{
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (c == '\r' && i < text.Length - 1 && text[i + 1] == '\n') continue;
if (c == '\r' || c == '\n') { AppendLine(); continue; }
CurrentLine.Add(new Char(c, style));
}
}
public void AppendLine(string text, StyleIndex style = StyleIndex.None)
{
Append(text, style);
AppendLine();
}
public void AppendLine()
{
CurrentLine = CreateLine();
lines.Add(CurrentLine);
}
public override void Initialized()
{
// Solution similar to CustomTextSourceSample.cs (not more than necessary)
// (an alternative is OnTextChanged(0, lines.Count - 1) which invokes TextChanged but there may be side effects)
if (CurrentTB.WordWrap)
{
OnRecalcWordWrap(new TextChangedEventArgs(0, lines.Count - 1));
}
CurrentTB.Invalidate();
}
}
在TextSource
类中添加这个虚方法:
/// <summary>
/// 当CurrentTB初始化此文本源时调用。
/// </summary>
public virtual void Initialized()
{
}
在FCTB
类的InitTextSource
方法中添加这行:
while (LineInfos.Count < ts.Count)
LineInfos.Add(new LineInfo(-1));
ts.Initialized(); // 添加这行
为了方便,更改Char
构造函数:
public Char(char c, StyleIndex s = StyleIndex.None)
{
this.c = c;
style = s;
}
使用方法如下:
var b = new TextBuilder(fctb);
b.Styles[0] = new MarkerStyle(Brushes.LightBlue);
b.Append("text", StyleIndex.Style0);
fctb.TextSource = b;
如果你不想重新编译FCTB
,你可以创建TextBuilder
类,去掉虚方法等,并在分配TextSource
后调用b.OnTextChanged(0, b.Count - 1)
。
英文:
Create a TextSource
-derived class:
public class TextBuilder : TextSource
{
public Line CurrentLine { get; private set; }
public TextBuilder(FastColoredTextBox t) : base(t)
{
AppendLine();
}
public void Append(string text, StyleIndex style = StyleIndex.None)
{
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (c == '\r' && i < text.Length - 1 && text[i + 1] == '\n') continue;
if (c == '\r' || c == '\n') { AppendLine(); continue; }
CurrentLine.Add(new Char(c, style));
}
}
public void AppendLine(string text, StyleIndex style = StyleIndex.None)
{
Append(text, style);
AppendLine();
}
public void AppendLine()
{
CurrentLine = CreateLine();
lines.Add(CurrentLine);
}
public override void Initialized()
{
// Solution similar to CustomTextSourceSample.cs (not more than necessary)
// (an alternative is OnTextChanged(0, lines.Count - 1) which invokes TextChanged but there may be side effects)
if (CurrentTB.WordWrap)
{
OnRecalcWordWrap(new TextChangedEventArgs(0, lines.Count - 1));
}
CurrentTB.Invalidate();
}
}
Add this virtual method to the TextSource
class:
/// <summary>
/// Called when CurrentTB has initialized this text source.
/// </summary>
public virtual void Initialized()
{
}
In the FCTB class, add this line to the InitTextSource
method:
while (LineInfos.Count < ts.Count)
LineInfos.Add(new LineInfo(-1));
ts.Initialized(); // Add this line
Change the Char
constructor for convenience:
public Char(char c, StyleIndex s = StyleIndex.None)
{
this.c = c;
style = s;
}
Use as follows:
var b = new TextBuilder(fctb);
b.Styles[0] = new MarkerStyle(Brushes.LightBlue);
b.Append("text", StyleIndex.Style0);
fctb.TextSource = b;
If you want to do it without recompiling FCTB you can just create the TextBuilder
class minus virtual method etc. and call b.OnTextChanged(0, b.Count - 1)
after assigning TextSource
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论