-1

What I want to do is a program that includes textbox (or something else that allows me to do it ) and this textbox is going to show the text from my resource .txt file and this is going to be like one word after another or two words after another for users to improve eye-movement on the text. To make it more clear the textbox is going to show the words two by two . I can do it by using string array but it only works on Listbox and Listbox is not okay for this project because it goes vertical and I need horizontal text like as we see in books.

And this is the code that shows the logic of what ı want but ı cannot use it it stops when I click the button.

{
    public Form1()
    {
        InitializeComponent();
    }

    string[] kelimeler;


  

    private void button1_Click(object sender, EventArgs e)
    {
        const char Separator = ' ';
        kelimeler = Resource1.TextFile1.Split(Separator);

    }


    private void button2_Click(object sender, EventArgs e)
    {
        for (int i = 0; i< kelimeler.Length; i++)
        {
            textBox1.Text += kelimeler[i]+" " ;

            Thread.Sleep(200);


        }


        
    }
}
bornemhu
  • 41
  • 8
  • You have a loop whose contents updates the I and then sleeps. In traditional Windows code, the UI will only update _after_ a message handler (here the button click handler) returns. If you wait long enough for all that sleeping to finish (how big is `kelimeler.Length`), you should see the last word. The traditional way to get around this would be to post a message back to the window and have that handler update the screen. But, `async` and `await` can probably do the trick. Make your handler `async` and use `await Task.Delay(200)` instead of `Thread.Sleep` – Flydog57 Jun 30 '21 at 21:49
  • Take a look at Microsoft's Reactive Framework. Then you can do this: `kelimeler.ToObservable().Scan("", (a, x) => $"{a} {x}").Zip(Observable.Interval(TimeSpan.FromMilliseconds(200.0)), (s, z) => s).ObserveOn(textBox1).Subscribe(x => textBox1.Text = x);` – Enigmativity Jun 30 '21 at 23:04

1 Answers1

1

Here's how to do it with async and await. It uses async void, which is generally frowned upon, but it's the only way I know how to make a button handler async.

I don't fish the starting string out of resources, I just do this:

private const string Saying = @"Now is the time for all good men to come to the aid of the party";

And, I carved of the retrieval and splitting of the string it's own function (that uses yield return to fabricate the enumerator).

private IEnumerable<string> GetWords()
{
    var words = Saying.Split(' ');
    foreach (var word in words)
    {
        yield return word;
    }
}

Then all that's left is the code that sticks the words in the text box. This code does what I think you want (puts the first word in the text box, pauses slightly, puts the next, pauses, etc.).

private async void button3_Click(object sender, EventArgs e)
{
    textBox4.Text = string.Empty;
    foreach (var word in GetWords())
    {
        textBox4.Text += (word + ' ');
        await Task.Delay(200);
    }
}
Flydog57
  • 6,851
  • 2
  • 17
  • 18
  • Thank you for the code I changed it little bit and now I can use it with the resource file and it works as I want . As a next step I m trying to find out how to back to the top of textbox because when the textbox is filled with the words the scrollbars shows up and I don't want that . I want to make it like book pages I mean when words arrives bottom of the textbox it automatically should turn to the top . Can you help me if you know about it ? – bornemhu Jul 01 '21 at 22:17
  • That would be worthy of another question. It won't be easy, the Textbox control is pretty stupid (it's a thin wrapper around the traditional User32 text box control). The `Lines` property returns an array of strings representing the lines of text in the control. You could measure the control (and remeasure it if its size changed), calculate the number of lines available and then monitor the Lines array to see if the number of lines in the control exceeds the space available, and then go from there. It would not be easy (and it would look a little hacked together) – Flydog57 Jul 01 '21 at 23:06
  • Lines would be useful but the textfile that I get text from is not written in order I mean it starts with line 1 and this goes really much . There are nearly 500 words between line 1 and line 2 so it is not useful . – bornemhu Jul 02 '21 at 17:30
  • And if it is possible I can use richtextbox or something else – bornemhu Jul 02 '21 at 20:22
  • I don't understand. As you write words in a multiline text box (with WordWrap=true), the words will wrap onto a new line. You'll get maybe 12 words per line. If you measure how much space your characters take in your textbox (see `Graphics.MeasureString` ) and you count how many lines you have in the text box (`Textbox.Lines.Count` ), you should be able to tell when you've filled the text box. When you get to N lines + 1, empty the text box and start over filling it. Or, if you want scrolling behavior, set the selection to the last possible position, SelectionWidth=0 and ScrollToSelection – Flydog57 Jul 03 '21 at 02:02