I have code to set text of TexBox as
textBox1.Text = s;
where s is a string that have more than 100,000 char, and it take long time to show text on textBox.
Anybody have solution to make it faster ?
To do that split the s string into many strings, and use the AppendText to add those subStrings, if you check MSDN you will see that :
The AppendText method enables the user to append text to the contents of a text control without using text concatenation, which, can yield better performance when many concatenations are required.
public string s = "Put you terribly long string here";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//For responsiveness
textBox1.BeginInvoke(new Action(() =>
{
//Here's your logic
for (int i = 0; i < s.Length; i += 1000)
{
//This if is just for security
if (i+1000 > s.Length)
{
//Here's your AppendText
textBox1.AppendText(s.Substring(i, s.Length-i));
}
else
{
//And it's here as well
textBox1.AppendText(s.Substring(i, 1000));
}
}
}));
}
I used the value 1000, you can use 1500 , 2000 , choose the one that gives better result.
Hope this helps.
Update :
AppendText is available for both WindowsForms and WPF, too bad can't find it on WindowsPhone and WinRT. so I think this solution may help you a lot
break s in sub strings and when you pass first sub string to the text box it will appear after that it concatenate to the second and so on.
other way is that use loop to set the value
for(int i=0;i<s.length; i++)
{
textBox1.Text += s[i];
}
may these helps you
Related
How can I add a function to a button that will run a method I've created. I want to write out an array into a message dialog box with a press of a button, but I don't seem to be getting anywhere so i turned to stackoverflow for some help, since googling didn't really help me with my problem.
static void Tractors(Tractor[] tractors)
{
for (int i = 0; i < tractors.Length; i++)
{
Console.WriteLine((i + 1) + ", " + tractors[i].ToString());
}
}
This is my function that writes out the table of "Tractors".
private void button1_Click(object sender, EventArgs e)
{
}
What should I write into the button1_click method so that it would work?
You need to bind the event handler with the button control and write the logic inside this event handler. If its windows form application you can do like this.
this.button1 = new System.Windows.Forms.Button();
this.button1.Click += new System.EventHandler(this.button1_Click);
private void button1_Click(object sender, EventArgs e)
{
//Call your methods here
}
You would call Tractor() the exactly same way you call Console.WriteLine(). Both are static functions.
However the function is utterly messed up and propably not salvageable. The proper name would be printTractorsToConsole(). As it contains the Console.WriteLine() call, it is strongly tied to Console Applications - avoid tying functions to one Display Technology like that.
You need a more general function that creates and returns a string. You can then send that string to WriteLine(), assign it to Label.Text or wherever else you want the string to be. Strings primarily exist for intput from or output towards the user - and there is too many ways to get it to them.
//Not tested against a compiler, may contain syntax errors
static string TractorArrayToString(Tractor[] tractors){
string output = "";
for (int i = 0; i < tractors.Length; i++)
{
output += (i + 1) + ", " + tractors[i].ToString()) + Environment.NewLine;
}
return output;
}
But even function might be a bad idea, as that function would tie all representations to a single format. Generally you would write that loop directly into the Click Event. But this function looks like it is for printing for debug purposes, so it might work.
When I clicked button starts for loop from i=0 and I want to see on the label value of i. However I only see last values of i.
public partial class Form1 : Form
{
int i;
public Form1()
{
InitializeComponent();
}
private void btnclick_Click(object sender, EventArgs e)
{
for ( i = 0; i < 3; i++)
{
lblForLoopExample.Text = i.ToString();
System.Threading.Thread.Sleep(1000);
}
}
}
when I run the my code I only see on the label ; 2 .
I want to see such a like below;
When the started For loop, i = 0, I must see the 0 on the Label.Text. An then when the i = 1, I must see 1 on the label.Text. And when i = 2, I must see 2 on the Label.Text.
I added Thread.Sleep(1000) however, result didn't change.
Where I am make mistake?
Please help me,
if you help me , I will appreciate you.
Thanks,
You need to append the lbl to get all the values. Right now, it finishes the loop and give you the last value in your label
public partial class Form1 : Form
{
int i;
public Form1()
{
InitializeComponent();
}
private void btnclick_Click(object sender, EventArgs e)
{
for ( i = 0; i < 3; i++)
{
lblForLoopExample.Text + = i.ToString();
}
}
}
Your problem is that you're doing work on the UI thread while expecting the UI thread to update your form.
While you process your loop, the UI thread is actually executing this code. The UI thread is therefore unable to update the form with the intermediate values you are setting within the loop. Once your code completes, the UI thread is then free to update the form. That's why you see the last value only.
You can see this better if you updated your code to loop ten million times instead of 3. Your form will become unresponsive and will appear locked up. That's because Windows knows your UI thread is locked in an intensive process and is unable to update the UI.
The solution is to use a background thread to run your process and synchronize updates with the UI thread. You'll also have to slow your loop down to see the changes, as others have suggested.
To learn more about how the UI thread works, and how to synchronize background threads with it, read this article (it's about WPF, but it covers the general case).
Each loop you re-write the string. Instead of saying
lblForLoopExample.Text = i.ToString();
You need to add to the string on each iteration. I'd create a variable to hold the value, and so something like this:
string myString = string.Empty;
for(i=0;i < 3; i++)
{
myString += i.ToString() + ", ";
}
lblForLoopExample.Text = myString.substring(0, (myString.length - 1));
substring is just so you don't have that trailing comma. It's kind of dirty code, but it will work.
First of all, your code won't compile as you are missing the exact format of the ToString() method in i.ToString along with the ;
lblForLoopExample.Text = i.ToString();
^^^
As per your code, you should try this:
for ( i = 0; i < 3; i++)
{
lblForLoopExample.Text += i.ToString() + ", ";
}
I am extremely very new to C#, just wrote some calculator, text editors and DB client in the school almost 10 years ago :) Not I am trying to make a tool for myself and my colleagues to view traces and logs in easier way. All we know Notepad++, we used daily for text highlighting, styling, but the thing is that these highlights get lost after you close Notepad++.
So my goal now is to make the same text editor but so it will be able to save your work.Currently I am working on the feature so when I am selecting some text, it will search for the same on whole document and highlight it, for example with red background. I added this one:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
int startIndex = 0;
while (startIndex<richTextBox1.TextLength)
{
int wordStartIndex = richTextBox1.Find(richTextBox1.SelectedText, startIndex, RichTextBoxFinds.None);
if (wordStartIndex != -1)
{
richTextBox1.SelectionStart = wordStartIndex;
richTextBox1.SelectionLength = richTextBox1.SelectionLength;
richTextBox1.SelectionBackColor = Color.Red;
}
else
break;
startIndex += wordStartIndex + richTextBox1.SelectionLength;
}
}
But it gives me "StackOverFlow" as I have a loop here. Can you please assist me with it?
I think I need to run 2 searches to avoid loop - one before selection index, one after. Or maybe there is easier option?
Thank you all, guys!
You're getting an infinite loop because you're in an event that checks for a selection change, and then in that event, you're changing the selection, which causes an event, where you change the selection, which causes an event...
If you want to avoid this you'll need a class level variable like
bool inSelectionChangeEvent;
and then change your code to:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
if (!inSelectionChangeEvent){
inSelectionChangeEvent = true;
}
else{
return;
}
...
Also, you're writing your OWN text editor? Err, there may be a simpler solution :)
Your problem is with the selection length. Right here:
richTextBox1.SelectionLength = richTextBox1.SelectionLength;
It does no good to set something equal to itself and I'm guessing this was an accident. When the SelectionLength is 0, startIndex never increases (anything + 0 is anything).
The first thing I'd do is check if richTextBox1.SelectionLength < 1 and if it is, just return from the method without doing anything.
This code snippet from MSDN should help you accomplish what you're doing:
string wordToFind = "melp";
int index = richTextBox1.Text.IndexOf( wordToFind );
while( index != -1 )
{
richTextBox1.Select( index, wordToFind.Length );
richTextBox1.SelectionColor = Color.Red;
index = richTextBox1.Text.IndexOf( wordToFind, index + wordToFind.Length );
}
I have written a little program. It works almost as I want, I just have one problem. I am trying to copy all functions I have found in the other program.
I have a TextBox, when the user can write a phone number. Firstly, he is only allowed to use digits and "+"and "-", so I use:
private void textBoxPhoneNumber_KeyPress(object sender, KeyPressEventArgs e)
{
if ((char.IsDigit(e.KeyChar) == false) && (e.KeyChar != '+') && (e.KeyChar != '-') && (e.KeyChar != '\b')) e.Handled = true;
}
Then I want the phone number to be in certain format (+12-34-1234567), so I use:
private bool IsPhoneNumberCorrect(string name)
{
return Regex.IsMatch(name, #"^+\+[0-9]{2}-[0-9]{2}-[0-9]{7}$", RegexOptions.None);
}
and finally this (with TextChange):
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
}
I use counter4 as a part of method (checkIfOk) that enables button. There is also an "X" icon that changes into "tick" when the number is given in proper format.
It works perfectly for me (just like in the program I am copying) - when the user writes something in the TextBox, he can only use digits and "+" and "-" and when the format is ok the icon changes and when other textboxes are also ok, the Ok buton enables.
Now, finally, the problem:
I am able to paste something from the Clipboard. In the original program, when I paste something with letters, digits and other signs, only digits and "+" and "-" remains. My program accepts everything in such situation.
I've been looking for something that might be helpful, but all I have found was very complicated. Is there a way to do it?
I tried to do something like this. It causes that when pasting only digits and "+" and "-" remains as it should, but the user can't write anything.
I am still a beginner. Maybe I am making a simple mistake?
private void phoneNumberValidity(object sender, EventArgs e)
{
Regex regex = new Regex("[^0-9-+]");
if (regex.IsMatch(Clipboard.GetText()))
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
checkIfOk();
textBoxPhoneNumber.Focus();
}
}
I am trying to do something like this:
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
Regex regex = new Regex("[^0-9-+]");
if (textBoxPhoneNumber.Text.Contains("a"))
{
if (regex.IsMatch(Clipboard.GetText()))
{
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
}
}
I know that it's not exactly what I want, but maybe someone can give some clues...
Generally i thought, that I'd like to check if the text in tb contains some unwanted elements, but I don't know how to check it. As you can see, it checks only one unwanted element.
First of all, please use TRY-Catch for the Convert.ToInt32 !
Second: Use TextChanged event, and validate the input with the actual content of the TextBox
To validate, you can do something similar:
string output = ""
string clipboardText = GetClipboardText()
for each chara in clipboardText's characters
if chara.isNumeric or chara=='+' or chara == '-'
output += chara
end foreach
Of course its just a simple soultion, but you can confgure it as you want.
Or if you want more complex way, you can play with the regex... Start with number or + - BUT not contains alphabetical char. Based on your request.
This is what I made, and it works :) I will only add try-catch block as Krekkon has suggested.
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
if (Regex.IsMatch(textBoxPhoneNumber.Text, "[^0-9-+]"))
{
Regex regex = new Regex("[^0-9-+]");
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
checkIfOk();
textBoxPhoneNumber.Focus();
}
Maybe it will help someone in the future.
Maybe you should try like this: leave the first version of phoneNumberValidity method as it is and then check if the tb Text has some unwanted elements, get rid of them.
I would like to use a RichTextBox WPF control to print log outputs, but I am wondering what is the most efficient way to remove the "oldest" lines after there are for example more than 10,000 lines displayed, if it is possible to actually implement a queue behaviour, especially as there is no easy "Text" property to play with.
Unfortunately, I am not able to achieve this result with nlog either probably due to a bug or a limitation.
You can use a Queue<string> to store your log messages, and display them using the RichTextBox.Lines property.
For example:
private const int _maxCapacity = 10000;
private Queue<string> _messageQueue = new Queue<string>(_maxCapacity);
private void button1_Click(object sender, EventArgs e)
{
if (_messageQueue.Count >= _maxCapacity)
{
_messageQueue.Dequeue();
}
_messageQueue.Enqueue("message " + _count++.ToString());
richTextBox1.Lines = _messageQueue.ToArray();
}
If you want the most recent messages to appear on top, reverse the queue:
richTextBox1.Lines = _messageQueue.Reverse().ToArray();
If you extend the original control with a LineCount int property, it is possible to use this (inspired by some code given here):
if (this.MaxLines > 0)
{
this.lineCount++;
if (this.lineCount > this.MaxLines)
{
tr = new TextRange(rtbx.Document.ContentStart, rtbx.Document.ContentEnd);
tr.Text = tr.Text.Remove(0, tr.Text.IndexOf('\n'));
this.lineCount--;
}
}
//And for auto scrolling
if (this.AutoScroll)
{
rtbx.ScrollToEnd();
}