homewark halp
homewark halp

Reputation: 9

C# Temperature Converter

I am trying to create a temperature converter and everything is working great.

    private void hsbTemperature_Scroll(object sender, ScrollEventArgs e)
    {
        TempFah = hsbTemperature.Value;
        txtCelsius.Text = Convert.ToString(TempFah);
        TempCel = Convert.ToInt32((TempFah - 32) * 5 / 9);
        txtFahrenheit.Text = TempCel.ToString();
    }

    private void hsbTemperature_ValueChanged(object sender, EventArgs e)
    {
        TempFah = hsbTemperature.Value;
        txtCelsius.Text = Convert.ToString(TempFah);
        TempCel = Convert.ToInt32((TempFah - 32) * 5 / 9);
        txtFahrenheit.Text = TempCel.ToString();
    }
}

However, when i try to change the value for the Fahrenheit textbox,the value of Celsius's textbox does not change and vise-versa. The values for both of the textboxes only change when i move the scrollbar.

So what i require is that when i change the value for my Fahrenheit i want the value for Celsius to also change and vise-versa.

Please help, Thank You.

Upvotes: 0

Views: 1035

Answers (1)

Rufus L
Rufus L

Reputation: 37060

Here's what I would do:

It looks like you already have these class level properties defined:

private int TempFah;
private int TempCel;

Also, you don't need to put any code in the Scroll event. ValueChanged is really what we care about, and it will get called right after Scroll anyway.

private void hsbTemperature_Scroll(object sender, ScrollEventArgs e)
{
    // Don't use this method when you really care about the value
}

So that we don't end up in any infinite loops of property change events triggering each other, I created a private bool variable to keep track of whether we are updating the text fields programmatically or not (as opposed to the user doing it). If this is set to true, then we don't need to process any code in the change events because the UpdateTempFields method (coming up) is already doing it.

private bool programIsUpdatingProperties = false;

Just to help separate out the code into re-usable parts, we can create a separate function to get the Celsius value from a Fahrenheit value. And while we're at it, make one that does the opposite:

private int GetCelciusValue(int fahrenheitValue)
{
    return (fahrenheitValue - 32) * 5 / 9;
}

private int GetFahrenheitValue(int celsiusValue)
{
    return celsiusValue * 9 / 5 + 32;
}

Now it's time to create the UpdateTempFields method which, given a Fahrenheit temperature, knows how to update all the control values on the form.

One trick to ensure that we don't over-set the hsbTemperature.Value (the user could enter one that's too big or small) is to use the smallest of either the hsbTemperature.Maximum or the number, and to ensure we don't under-set it, we get the maximum value of either the hsbTemperature.Minimum or the number. This is done below using Math.Max and Math.Min below:

private void UpdateTempFields(int newFahrenheitTemp)
{
    // Let the rest of the code know this is us, not the user
    programIsUpdatingProperties = true;

    TempFah = newFahrenheitTemp;
    TempCel = GetCelciusValue(TempFah);

    txtCelsius.Text = TempCel.ToString();
    txtFahrenheit.Text = TempFah.ToString();

    // Ensure we don't try to set the scroll bar to a value it can't handle
    hsbTemperature.Value =
        Math.Max(hsbTemperature.Minimum,
            Math.Min(hsbTemperature.Maximum, TempFah));

    // Carry on as normal now...
    programIsUpdatingProperties = false;
}

Now, in the change events for our controls, all we have to do is call the UpdateTempFields() method with a Fahrenheit value, and it will take care of the rest. But we only want to do this if the user is the one changing the value, so check our flag first:

private void txtFahrenheit_TextChanged(object sender, EventArgs e)
{
    if (!programIsUpdatingProperties)
    {
        int fahrValue;
        // Use int.TryParse to ensure it's a valid integer (if it's not, do nothing)
        if (int.TryParse(txtFahrenheit.Text, out fahrValue))
        {
            UpdateTempFields(fahrValue);
        }
    }
}

private void txtCelsius_TextChanged(object sender, EventArgs e)
{
    if (!programIsUpdatingProperties)
    {
        int celsiusValue;
        // Use int.TryParse to ensure it's a valid integer (if it's not, do nothing)
        if (int.TryParse(txtCelsius.Text, out celsiusValue))
        {
            // Convert celcius to fahrenheit first
            var fahrValue = GetFahrenheitValue(celsiusValue);
            UpdateTempFields(fahrValue);
        }
    }
}

private void hsbTemperature_ValueChanged(object sender, EventArgs e)
{
    if (!programIsUpdatingProperties)
    {
        UpdateTempFields(hsbTemperature.Value);
    }
}

Upvotes: 2

Related Questions