I am using RichTextBox and TextBox for showing some information which is collected during several days. So there are a lot of strings inside it after couple days and I get OutOfMemory exception. I think this error occurs because of lots of data. Is there some properties or functions which allow to limit number of strings inside RichTextBox and TextBox? I need to truncate only old strings which are in the beggining of list. For instance, take a look at picture below:
Any ideas?
I created simple code which allows me to resolve this problem.
For TextBox:
if (limitLines>0 && simpleTextBox.LineCount > limitLines)
{
string tempText = "";
for (int i = simpleTextBox.LineCount-limitLines; i < simpleTextBox.LineCount; i++)
{
tempText += simpleTextBox.GetLineText(i);
}
simpleTextBox.Clear();
simpleTextBox.Text = tempText;
}
simpleTextBox.AppendText(data);
For RichTextBox:
TextRange tr = new TextRange(richTextBox.Document.ContentEnd, richTextBox.Document.ContentEnd);
tr.Text = text + "\r\n";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, solidColorBrush);
if (limitLines > 0 && richTextBox.Document.Blocks.Count > limitLines)
{
for (int i = richTextBox.Document.Blocks.Count - limitLines; i < richTextBox.Document.Blocks.Count; i++)
richTextBox.Document.Blocks.Remove(richTextBox.Document.Blocks.FirstBlock);
}
I hope it helps to someone else!
Related
I am trying to make a simple WYSIWYG editor. I found pretty difficult to format the rtb.
It is supposed to format basic things like bold, italic, coloring(and mixed).
What have I found and tried so far:
private void boldButton_Click(object sender, EventArgs e)
{
int start = rtb.SelectionStart;
int length = rtb.SelectionLength;
for (int i = start, max = start + length; i < max; ++i)
{
rtb.Select(i, 1);
rtb.SelectionFont = new Font(rtb.Font, rtb.SelectionFont.Style | FontStyle.Bold);
}
rtb.SelectionStart = start;
rtb.SelectionLength = length;
rtb.Focus();
}
rtb = richtextbox.
This works as expected, but is terribly slow.
I also found the idea about using and formatting directly the RTF, but the format seems too complicated and very easy to mistake it.
I hope it is a better solution.
Thank you.
The performance hit is probably down to the fact you're looping through each character instead of doing everything in one go:
var start = this.rtb.SelectionStart;
var length = this.rtb.SelectionLength;
this.rtb.Select(start, length);
this.rtb.SelectionFont = new Font(this.rtb.Font, this.rtb.SelectionFont.Style | FontStyle.Bold);
I've had the same problem myself. Interestingly, I found out that you can speed up formatting by an order of magnitude if you refrain from referencing to the control's properties when looping through. Instead, put the necessary control properties in separate variables before entering the loop. For instance, instead of continuously referencing e.g. richTextBox1.Length, replace with int len = richTextBox1.Length, and then refer to len inside the loop. Instead of referencing to richTextBox1.Text[index], replace with string text = richTextBox1.Text before the loop, and then instead text[index] inside the loop.
i.e for instance consider this sentence. "This is my sentence." I want the program to display highlighting first 'This' then 'is' and so on. can this actually be done? should i use a timer ? help with brief explanation is greatly appreciated. Thanks in advance.
A timer is a good option if you don't want the UI to be blocked all the time. A very basic solution for your problem is the following:
Add this to your initialization code:
// index of highlighted text block
var i = 0;
var timer = new Timer()
{
Interval = 300
};
timer.Tick += new EventHandler((sender, e) =>
{
// split the elements to highlight by space character
var textElements = this.richTextBox1.Text
.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries)
.ToArray();
// avoid dividing by zero when using modulo operator
if (textElements.Length > 0)
{
// start all over again when the end of text is reached.
i = i % textElements.Length;
// clear the RichTextBox
this.richTextBox1.Text = string.Empty;
for (var n = 0; n < textElements.Length; n++)
{
// now adding each text block again
// choose color depending on the index
this.richTextBox1.AppendText(textElements[n] + ' ', i == n ? Color.Red : Color.Black);
}
// increment the index for the next run
i++;
}
});
timer.Start();
This solution uses an extension method. To use this, you must add an extension class like this:
static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox richtTextBox, string text, Color color)
{
richtTextBox.SelectionStart = richtTextBox.TextLength;
richtTextBox.SelectionLength = 0;
richtTextBox.SelectionColor = color;
richtTextBox.AppendText(text);
richtTextBox.SelectionColor = richtTextBox.ForeColor;
}
}
You can get more information about the extension method I used here.
The drawback of this solution is that the RichTextBox is not realy useable while the highlighting is going on. If you want the user to input some text, you should stop the timer first.
when i creat unlimited textbox in gridview dynamically how can i access them?
for example:
int uste_uzaklik = 30;
int nesne = ListBox1.Items.Count;
Array.Resize(ref textboxarray, nesne * nesne);
for (int str = 0; str < nesne; str++)
{
for (int stn = 0; stn < nesne; stn++)
{
textboxarray[idm] = new TextBox();
textboxarray[idm].Font.Bold = true;
textboxarray[idm].Font.Name = "Verdana";
textboxarray[idm].ID = idm.ToString();
textboxarray[idm].ToolTip = textboxarray[idm].ID;
GridView2.Rows[str].Cells[stn + 1].Controls.Add(textboxarray[idm]);
if (str == stn) textboxarray[idm].Enabled = false;
uste_uzaklik += 30;
idm++;
}
}
i add texboxes in gridview...you can imagine a matris...
there is no problem...
but when i access them like this:
if (((TextBox)(GridView2.Rows[str].Cells[stn].FindControl(idm.ToString()))).Text != null)
{
matris[i, j] = Convert.ToInt32(GridView2.Rows[str].Cells[stn].Text);
}
occur an error
Object reference not set to an instance of an object.
how can i solve this problem?
References you have to controls don't cease to exist you add them to another control. You've already created an array of your TextBoxes, and you should use that to access them instead of trying to dig into the GridView in which you've added them every single time you want to change them.
Granted, you're going from a one-dimensional array of TextBoxes to a two-dimensional layout within the GridView, so you'll either have to find some way to establish how the indices match up between the two. Or, more easily, you could just turn textboxarray into a two-dimensional array and just have it exactly match the way it's laid out in the GridView. Either way, I think it'll be a lot less work than having to muck around in the GridView.
I have a hidden input that contains some objects in it. I put string "#" between any two objects, but I want to put a string that isn't on keyboard. How can I do it?
for (int i = 0; i < MyTable.Rows.Count; i++)
{
txtRows.Value += MyTable.Rows[i]["Row"].ToString();
if (i < MyTable.Rows.Count - 1)
{
txtRows.Value += "#";
}
}
You can put any character you like in between two strings. For example to use the ASCII record separator character, use this:
if (i < MyTable.Rows.Count - 1)
{
txtRows.Value += '\x1e';
}
And then split the value back into multiple strings using the Split method:
string[] values = txtRows.Split('\x1e');
However, I'd recommend using an array or list of inputs instead:
for (int i = 0; i < MyTable.Rows.Count; i++)
{
txtRows[i].Value = MyTable.Rows[i]["Row"].ToString();
}
Of course, you'll probably have to modify how you add these hidden elements to your form, but it's a much nicer way of handling these sorts of problems.
I'm currently coding a project that can take up to 200 entries of a specific product, as determined by user input. Basically, my GUI loads, and I use jQuery to dynamically build the entries whenever there is a change to the amount field. When using jQuery, I simply give each of them ids in the form of variable1, variable2, ...., variableX (where X is the amount of entries indicated). Small snippet of code to clarify:
for(var i = 1;i <= amount_selected; i++) {
$('table_name tr:last').after('<tr><td><input type="text" id="variable' + i + '"></td></tr>');
}
Now when I try to move to the back end, I'm trying to reference these variable names by putting them in a list. I went ahead and put them in a list of HtmlInputText, to call the Variable names from the list itself. (This would save having to call all (up to 200) methods manually, which is really not an option).
So what I did (in C#) was:
List<HtmlInputText> listvar = new List<HtmlInputText>();
for(int i = 1; i <= amount_selected; i++) {
string j = "variable" + Convert.ToString(i);
HtmlInputText x = j;
listvar.Add((x));
samplemethod(listvar[i]);
}
But it's not working at all. Does anyone have any ideas as to how this would be done, without doing so manually? I know my logic might be completely off, but hopefully this illustrates at least what I'm attempting to do.
I'm assuming these inputs are in a form? If you're submitting then you can access the text boxes from the Request object:
List<string> results = new List<string>();
for (int i = 1; i <= amount_selected; i++)
{
string s = String.Format("{0}", Request.Form["variable" + Convert.ToString(i)]);
results.Add(s);
}
you could do $("#variable" + Convert.ToString(i)).val()