Search code examples
c#xamarin.formsconsole.readline

(C#) (Xamarin.Forms) Custom ReadLine(), pause code for user response


I'm trying to create a custom ReadLine() method in a custom Console class.

I want to create a Console application on Android and iOS by using Xamarin.Forms.

This is my Console class right now:

public class DHConsole
{
    protected static Entry inEntry;
    protected static Label outLabel;
    protected static bool write = false;
    public static bool completed = false;

    /// <summary>
    /// Gets the in output.
    /// </summary>
    /// <param name="edit">Edit.</param>
    /// <param name="etr">Etr.</param>
    public static void GetInOutputX(Label oLabel, Entry iEntry)
    {
        outLabel = oLabel; // Xamarin.Forms.Label
        inEntry = iEntry;  // Xamarin.Froms.Entry
    }

    /// <summary>
    /// Write the specified output.
    /// </summary>
    /// <returns>The write.</returns>
    /// <param name="output">Output.</param>
    public static void Write(string output)
    {
        outLabel.Text += output;
        write = true;
    }

    /// <summary>
    /// Writes the line.
    /// </summary>
    /// <param name="output">Output.</param>
    public static void WriteLine(string output)
    {
        // Check if there already is set the method Write().
        if (!write)
        {
            // Set the output on a new line.
            outLabel.Text += "\n";
        }
        else
        {
           // Set the output on the current line.
           // And set write to false.
            write = false;
        }

        outLabel.Text += output;
    }

    /// <summary>
    /// Reads the line.
    /// </summary>
    /// <returns>The line.</returns>
    public static string ReadLine()
    {
        //GetLine(inEntry.Text).Wait();

        //completed = false;
        outLabel.Text += inEntry.Text;

        return inEntry.Text;
    }

    /// <summary>
    /// Reads the key.
    /// </summary>
    /// <returns>The key.</returns>
    public static string ReadKey()
    {
        string input = inEntry.Text;
        return input[input.Length - 1].ToString();
    }

    //protected async static Task GetLine(string entryText)
    //{
    //    Task<string> textTask = entryText;
    //    string text = await textTask;
    //}
}

The idea is to get the Console.WriteLine() and custom Console.ReadLine() on the screen like this:

        DHConsole.WriteLine("What is the firstname of this new User?");
        string firstname = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the lastname of this new User?");
        string lastname = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the username of this new User?");
        string username = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the name of the street of this new User?");
        string street = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the house number of this new User?");
        string houseNumber = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the name of the city of this new User?");
        string city = DHConsole.ReadLine();

        DHConsole.WriteLine("What is the name of the country of this new User?");
        string country = DHConsole.ReadLine();

        DHConsole.WriteLine("Do you want to continue registering?[Yes/No]");
        string sContinue = DHConsole.ReadLine();

        if (IsEqualCI(sContinue, "Yes"))
        {
            users.Add(new User
            {
                Id = createId(users),
                FirstName = firstname,
                LastName = lastname,
                UserName = username,
                Street = street,
                HouseNumber = houseNumber,
                City = city,
                Country = country
            });
        }
        else
        {
            DHConsole.WriteLine("OK, bye!");
        }

But the output comes like this: output

I tried the accepted answer on waiting for users response, but this doesn't work for my project.

Now my question is: How do I pause the code after each question, to wait for the user's response?

Thanks in advance!


Solution

  • What @Nkosi meant was to modify your ReadLine to following:

    TaskCompletionSource<string> _tcs;
    public Task<string> Readline()
    {
        _tcs = new TaskCompletionSource<string>();
    
        EventHandler handler = null;
        handler = new EventHandler((sender, args) =>
        {
            var entry = sender as Entry;
            _tcs.SetResult(entry.Text);
            entry.Text = string.Empty;
            entry.Completed -= handler;
        });
    
        var ctrl = inEntry;
        ctrl.Completed += handler;
        ctrl.Focus();
        return _tcs.Task;
    }
    

    Sample usage:

    string firstname = await DHConsole.ReadLine();
    

    Basically this code uses TaskCompletionSource and Completed event (which is fired when enter key is pressed).