我正在尝试创建一个温度转换器,一切都很好。
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();
}
}
但是,当我尝试更改华氏度文本框的值时,摄氏度文本框的值不会更改,反之亦然。两个文本框的值仅在我移动滚动条时更改。
所以我需要的是,当我改变华氏温度的值时,我希望摄氏度的值也会改变,反之亦然。
请帮助,谢谢。
答案 0 :(得分:2)
这就是我要做的事情:
看起来您已经定义了这些类级属性:
private int TempFah;
private int TempCel;
此外,您无需在Scroll
事件中添加任何代码。 ValueChanged
确实是我们关心的问题,无论如何都会在Scroll
之后立即调用。
private void hsbTemperature_Scroll(object sender, ScrollEventArgs e)
{
// Don't use this method when you really care about the value
}
因此,我们不会在任何触发对方的属性更改事件的无限循环中结束,我创建了一个私有bool
变量来跟踪我们是否以编程方式更新文本字段(相反)给用户这样做)。如果将其设置为true,那么我们不需要处理更改事件中的任何代码,因为UpdateTempFields
方法(即将出现)已经在执行它。
private bool programIsUpdatingProperties = false;
为了帮助将代码分离成可重复使用的部分,我们可以创建一个单独的函数来从华氏温度值中获取Celsius值。虽然我们正在努力,但要做出相反的事情:
private int GetCelciusValue(int fahrenheitValue)
{
return (fahrenheitValue - 32) * 5 / 9;
}
private int GetFahrenheitValue(int celsiusValue)
{
return celsiusValue * 9 / 5 + 32;
}
现在是时候创建UpdateTempFields
方法,在给定华氏温度的情况下,该方法知道如何更新表单上的所有控制值。
确保我们不会过度设置hsbTemperature.Value
(用户可以输入太大或太小)的一个技巧是使用hsbTemperature.Maximum
或数字中最小的一个,为了确保我们不设置它,我们得到hsbTemperature.Minimum
或数字的最大值。以下使用下面的Math.Max
和Math.Min
完成此操作:
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;
}
现在,在我们控件的更改事件中,我们所要做的就是使用华氏度值调用UpdateTempFields()
方法,它将处理其余的事情。但是如果用户是更改值的用户,我们只想这样做,所以首先检查我们的标志:
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);
}
}