I have two if-else conditions which will display some text on a Windows Forms textbox. This textbox has text set to it from a different thread other than the UI thread.
Context:
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.txtMessages.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtMessages.Text = text;
}
}
private void setTextFunc()
{
if(this condition is true)
{
setText("Hello from text 1" + Environment.NewLine);
}
else
{
setText("Hello from text 2" + Environment.NewLine);
}
}
Now the problem is that when Hello from text 2 text gets displayed, it overwrites the first text. I want it to go below and keep the first text.
How can I achieve this?
I thought about using a list collection as so:
List<string> listOfStrings = new List<string>();
listOfStrings.Add("Hello from text 1");
listOfStrings.Add("Hello from text 2");
Then iterating through this list collection. Will that do?
foreach(string x in listOfStrings)
{
MessageBox.Show(x);
}
Any suggestions? I considered a RichTextBox but seeing as I won't be editing the text at runtime, I see no need for it.
The problem you have is that:
this.txtMessages.Text = text;
In your setText method replaces the content of the Text property of your text field. If you want to add to the existing content, you should replace the code with something along the lines of:
this.txtMessages.Text = this.txtMessages.Text + text;
As your code suggests (thanks to the addition of Environment.NewLine in setTextFunc) that you always want to delimit the newly added text with a line-break, consider adding a new function along the lines of:
private void AppendText(string text)
{
// Code to trigger the Invoke here
else
{
this.txtMessages.Text = this.txtMessages.Text + Environment.newLine + text;
}
}
Doing this also allows you to encapsulate the behaviour of "add text with a new line" into a single method - at the moment your setTextFunc method has a really small amount of repeated code (adding Environment.NewLine) which you can elide by doing this.
Related
I made a program that text is moving right to left(marquee).
But, I can't make use multi-line text to label.
Who can help me?
single line text is good work. But if multi-line, just get last sentence.
private void timer1_Tick(object sender, EventArgs e)
{
string screentext = clsBas.SCREEN_TEXT;//include in Multi-line text;
string[] result = screentext.Split(new string[] { "\r\n" }, StringSplitOptions.None);
string space = " ";
foreach (string news in result)
{
lblScreenText.Text = news + space;
if (lblScreenText.Left < 0 && (Math.Abs(lblScreenText.Left) >
lblScreenText.Width))
lblScreenText.Left = lblScreenText.Width;
lblScreenText.Left -= 2;
}
}
Try using Environment.NewLine and append to text.
Better way to do it, is to use textbox multi-line and make it read-only.
I have a small problem, I have created a private chat message system using c#. Now what I need is a way to send a clickable link to other person.
When selecting a person from the list, I press invite button and a message comes to the messagebox like "to User1: join from this link"
private void InvBtn_Click(object sender, RoutedEventArgs e)
{
selectedUser = UsersListBox.SelectedItem.ToString();
if (selectedUser != login)
{
MessageBox.Show("Select other user than yourself");
return;
}
else
{
Msg.Text = selectedUser + " join from this 'link' ";
}
}
After sending the other person gets the message to RichTextBox saying
From user2: join from this link
There is no need for open a website, but other other form where will be more details.
You need to create custom MessageBox with Hyperlink button.
Try this out, here u need to set the height and width property properly....and make the constructor to accept the arguments so that users can design it the way they want.
public class CustomMessageBox
{
public CustomMessageBox()
{
Window w = new Window();
DockPanel panel = new DockPanel();
TextBlock tx = new TextBlock();
Paragraph parx = new Paragraph();
Run run1 = new Run("Text preceeding the hyperlink.");
Run run2 = new Run("Text following the hyperlink.");
Run run3 = new Run("Link Text.");
Hyperlink hyperl = new Hyperlink(run3);
hyperl.NavigateUri = new Uri("http://search.msn.com");
tx.Inlines.Add(hyperl);
panel.Children.Add(tx);
w.Content = panel;
w.Show();
}
}
Source : https://social.msdn.microsoft.com/Forums/vstudio/en-US/57fcd28b-6e9e-4529-a583-892c8f6d7cc8/hyperlink-in-wpf-message-box?forum=wpf
First you need to come up with a way to include your special markup in the text message. You can either pack the entire message in an existing container format (XML, JSON, etc.) or to keep things simple include special markers within the text, for example:
Hi User1, join from [This link:12345].
The same way you could include markup for other things like bold (**bold**), italics (*italics*), or actual hyperlinks to websites.
On the other side, you will need a parser that detects this special markup and replaces it with a clickable link. In the following example I'm using Regex to find and replace all text in the format [Text:Command].
private IEnumerable<Inline> Parse(string text)
{
// Define the format of "special" message segments
Regex commandFinder = new Regex(#"\[(?<text>.+)\:(?<command>.+)]");
// Find all matches in the message text
var matches = commandFinder.Matches(text);
// remember where to split the string so we don't lose other
// parts of the message
int previousMatchEnd = 0;
// loop over all matches
foreach (Match match in matches)
{
// extract the text fore it
string textBeforeMatch = text.Substring(previousMatchEnd, match.Index - previousMatchEnd);
yield return new Run(textBeforeMatch);
previousMatchEnd = match.Index + match.Length;
// extract information and create a clickable link
string commandText = match.Groups["text"].Value;
string command = match.Groups["command"].Value;
// it would be better to use the "Command" property here,
// but for a quick demo this will do
Hyperlink link = new Hyperlink(new Run(commandText));
link.Click += (s, a) => { HandleCommand(command); };
yield return link;
}
// return the rest of the message (or all of it if there was no match)
if (previousMatchEnd < text.Length)
yield return new Run(text.Substring(previousMatchEnd));
}
In the method where you receive the message, you can simply integrate it like this:
// Where you receive the text
// This probably is just a `txtOutput.Text += ` until now
private void OnTextReceived(string text)
{
txtOutput.Inlines.AddRange(Parse(text));
}
// the method that gets invoked when a link is clicked
// and you can parse/handle the actual command
private void HandleCommand(string command)
{
MessageBox.Show("Command clicked: " + command);
}
The message Hi User1, join from [this link:1234567890] will show up as Hi User1, join from this link and will invoke HandleCommand("1234567890") when clicked.
So I made this code that when key words are typed into the first text box ("TextEditor") it should give an output to another text box ("output"). So there are two moderately simple problems that I have no clue how to fix. (1) when you write one keyword in the TextEditor the proper output i shown. But when you write the other keyword that would be expected the out that was given for keyword number 1 is deleted and the output for keyword 2 is shown. It is supposed to show both keyword outputs but on separate lines. My second problem is I can't figure out how to make output (the second textbox) to have no output when there is no input in TextEditor After a keyword is written but then deleted.
So if I wrote: "create" output would show "Token: CREATE" but then if I wrote "Variable" after the "create" the output text would change from "Token: CREATE" to "Token: VARIABLE". I need the out put of both to be on separate lines so they don't cancel each other out. Now if I deleted whatever I had earlier, The output text would still show "Token: Variable" instead of having a blank textbox. Here is my code:
private void TextEditor_TextChanged(object sender, EventArgs e)
{
string input = TextEditor.Text;
if (input != " ")
{
string[] command = { "create", "if" };
if (input.ToLower().Contains(command[0]))
{
Output.Text = "Token: CREATE";
string[] type = { "variable", "boolean" };
if (input.ToLower().Contains(type[0]))
{
Output.Text = "Token: VARIABLE";
Output.AppendText(Environment.NewLine); //this is supposed to change to the next line but for some reason it doesnt.
string[] variable = { "value", "called" };
if (input.ToLower().Contains(variable[0]))
{
Output.Text = "Token: VALUE";
}
}
}
}
else
{
Output.Text = " ";
}
Well what you are doing is resetting your text variable to say either create or variable with =. You could just append += to your text variable rather then assigning it again. I just use \n to create newline, and append it to the text output. Not sure what you are writing this in I assumed wpf and it didn't seem to like the Environment.NewLine so I just got rid of it.
string input = TextEditor.Text;
if (input != " ")
{
string[] command = { "create", "if" };
if (input.ToLower().Contains(command[0]))
{
Output.Text = "Token: CREATE";
string[] type = { "variable", "boolean" };
if (input.ToLower().Contains(type[0]))
{
Output.Text += "\nToken: VARIABLE";
// Output. AppendText(Environment.NewLine); //this is supposed to change to the next line but for some reason it doesnt.
string[] variable = { "value", "called" };
if (input.ToLower().Contains(variable[0]))
{
Output.Text += "\nToken: VALUE";
}
}
}
}
else
{
Output.Text = " ";
}
When programming a Windows Forms application I found myself having to create a variable amount of text fields according to the number of inputs.
I decided to name these name1, name2, name3, ..., nameN.
Now I want to be able to save the user's input to a text file. To do this I need to get the text from the text boxes into separate variables to be able to write this to the text file.
This would result in a for loop like this:
for(i=0; i < totalnames; i++)
{
string varname= "name" + i;
}
But this way I cannot get the value from the text boxes. How can I get the separate values from the text boxes to write them to the text file?
Thank you,
When you create the form controls, keep references to them in a list:
// probably at the class level...
List<TextBox> myTextBoxes = new List<TextBox>();
// then when you create them...
myTextBoxes.Add(name1);
// etc.
Then later, when you need to reference them, use the list:
foreach (var textBox in myTextBoxes)
{
// get the value from the text box and use it in your output
}
You can create a List of string List and add your name in it. Then use StreamWriter to add the name in your file:
List<string> myListOfNames = new List<string>();
int totalnames = 10;
for (int i = 0; i < totalnames; i++)
{
myListOfNames.Add("name" + i);
}
using (StreamWriter writer = new StreamWriter("C:\\MyTextFile.txt", true))
{
foreach (string name in myListOfNames)
{
writer.WriteLine(name);
}
}
Here is my two pennies worth, because the OP originally said Windows Form Application - I would have a Save button, which when fired, the code behind will grab all the Textboxes and save to the file. You can add your own filtering for textboxes yourself if you want.
Firstly here is the code behind for the button event:
private void saveToFile_Click(object sender, EventArgs e)
{
using (StreamWriter writer = new StreamWriter("C:\\k\\saveToFile.txt", true))
{
if (this.Controls.Count > 0)
{
var textBoxes = this.Controls.OfType<TextBox>();
foreach (TextBox textbox in textBoxes)
{
writer.WriteLine(textbox.Name + "=" + textbox.Text);
}
}
}
}
A simple forn to prove the point, each TextBox has a name of name1 etc.
Also here is an example output of the file:
Improvements
Filtering on the Textboxes - you may only want to do this for some textboxes for a particular name.
Loading the file. I have added the textbox name to the file, so theorically you could load the data back into the textboxes.
How can i focus a Inline in a RichTextBox?
I Create a FlowDocument from a Text-File and load it in my richTextBox1
and mark one Inline after an other accordingly to a Button_click (be recreating the FlowDocument)
with this code:
richTextBox1.SelectAll();
richTextBox1.Selection.Text = "";
string text = System.IO.File.ReadAllText(file);
int iZeile = 0;
string[] split = text.Split(new string[] {"\r\n"},StringSplitOptions.None);
foreach (string s in split)
{
if (iZeile != 27)
{
paragraph.Inlines.Add(s + "\r\n"); // adds line added without marking
}
else
{
Run run = new Run(split[27]); // adds line with marking
run.Background = Brushes.Yellow;
paragraph.Inlines.Add(run);
paragraph.Inlines.Add("\r\n");
}
iZeile++;
}
FlowDocument document = new FlowDocument(paragraph);
richTextBox1.Document = new FlowDocument();
richTextBox1.Document = document;
Keyboard.Focus(richTextBox1);
}
I know its not.. perfect.
the Issue
It works so far but the problem that occurs is me Market Inline doesn't comes intoView. Is there a easy way to bring this Inline intoView?
The straightforward solution seemed to be FrameworkContentElement.BringIntoView() but after putting it in the code below it initially had no effect. As it turns out this is one of these timing issues (I've seen similar problems in WinForms) that can be solved by processing the outstanding Windows Messages. WPF has no direct equivalent of DoEvents() but there exists a well known substitute.
I placed this in a ButtonClick, changes marked with //**:
Paragraph paragraph = new Paragraph();
Inline selected = null; //**
richTextBox1.SelectAll();
richTextBox1.Selection.Text = "";
string text = System.IO.File.ReadAllText(#"..\..\MainWindow.xaml.cs");
int iZeile = 0;
string[] split = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
foreach (string s in split)
{
if (iZeile != 27)
{
paragraph.Inlines.Add(s + "\r\n"); // adds line added without marking
}
else
{
Run run = new Run(split[27]); // adds line with marking
run.Background = Brushes.Yellow;
paragraph.Inlines.Add(run);
paragraph.Inlines.Add("\r\n");
selected = run; // ** remember this element
}
iZeile++;
}
FlowDocument document = new FlowDocument(paragraph);
richTextBox1.Document = new FlowDocument();
richTextBox1.Document = document;
Keyboard.Focus(richTextBox1);
DoEvents(); // ** this is required, probably a bug
selected.BringIntoView(); // **
And the helper method, from here:
public static void DoEvents()
{
Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Background,
new Action(delegate { }));
}
you should try one of this methods
richTextBox.SelectionStart = richTextBox.Text.Length;
richTextBox.ScrollToCaret();
.
richTextBox.AppendText(text);
richTextBox.ScrollToEnd();
futher informations are here and here
Edit
ok after a bit of digging in the WPF RichTextBox i thing you cloud try richTextBox.ScrollToVerticalOffset(Offset)
to get the Offset maybe you could use this answer
EDIT 2
ok after some more research i found following Link where you can download this working example