Что вам нужно сделать, это сделать шаг назад и просто проигнорировать всю проблему WinForms. Попробуйте сначала решить конкретную проблему:
Я хочу написать программу, которая предложит пользователю ввести название места и ввести 2-значную температуру (F) в диапазоне от 20 до 100. Когда пользователь нажимает кнопку «ОК» в форме, которую я хочу чтобы в окне сообщения отображалось название места, в которое они вошли, и температура (F), которую они ввели, плюс его преобразование по Цельсию и сообщение об ошибке, если какое-либо из полей оставлено пустым или если температура выходит за пределы диапазона.
Что можно разбить на две разные проблемы:
- Введите значение температуры от 20 до 99 (поскольку вы указали две цифры)
- Перевести температуру в градусы Цельсия
Проверка - это то, что всегда должно быть сделано, поэтому я не рассматриваю это как отдельную проблему.
Следующее, что нужно сделать, это подумать о том, как вы хотите, чтобы решение работало. Всегда начинайте с решения, поскольку зачастую это проще, чем пытаться создать реализацию напрямую. Разработка через тестирование действительно хороша, поскольку она делает именно это.
Я бы хотел что-то вроде этого (псевдокод):
var fahrenheit = dialog.GetInput();
var celcius = fahrenheit.Convert(new FahrenheitToCelciusConverter());
resultDialog.Show(fahrenheit, celsius);
Определение объектов
Теперь, когда мы знаем, что мы хотим сделать, давайте больше сосредоточимся на фактической реализации. Посмотрев на псевдокод, мы определили, что нам нужна пара классов.
Прежде всего, нам нужно получить ввод
// the validation should be done in this form when the user
// presses OK. But that's up to you to figure out
public class PlaceAndTemperatureForm : Form
{
public PlaceAndTemperature GetPlaceAndTemperature()
{
return new PlaceAndTemperature(txtName.Text, int.Parse(txtTemperature .Text));
}
}
И так как нам нужно получить данные из формы, давайте создадим класс для их хранения:
public class PlaceAndTemperature
{
public PlaceAndTemperature(string name, int temperature)
{
Name = name;
Temperature = temperature;
}
public string Name { get; private set; }
public int Temperature { get; private set; }
}
Посмотрите на класс выше. Он имеет частные сеттеры, что означает, что никакой другой класс или код не может его изменить. Это называется неизменными объектами. Хорошо, что мы знаем, что это всегда безопасно и не может быть в неожиданном / недействительном состоянии. Вы должны всегда пытаться иметь неизменные объекты или, по крайней мере, не позволять никаким другим объектам изменять состояние без того, чтобы сам класс проверял изменения.
Далее идет конверсия. Мы написали следующий код:
var celcius = placeAndTempature.Convert(new FahrenheitToCelciusConverter());
Следовательно, нам нужно изменить класс, чтобы взять конвертер и вернуть новое место.
public class PlaceAndTemperature
{
public PlaceAndTempature(string name, int temperature)
{
Name = name;
Temperature = temperature;
}
public string Name { get; private set; }
public int Temperature { get; private set; }
public PlaceAndTemperature Convert(ITemperatureConverter converter)
{
return new PlaceAndTemperature(Name, converter.Convert(Temperature));
}
}
Я только что представил новую концепцию под названием Интерфейсы. Вы можете смотреть на них как на шаблоны слов или на синий рисунок. Они здесь, чтобы определить, как должен выглядеть класс, но не иметь никакой логики. Это спецификация.
public interface ITemperatureConverter
{
int Convert(int source);
}
Проблема теперь в том, что у нас есть два объекта PlaceAndTempera, первый с градусом Фаренгейта и один с градусами Цельсия Нам нужно уметь определить, какой тип юнитов используется, или, возможно, позже мы получим некоторые неприятные ошибки.
Позволяет добавить спецификацию устройства, используя enum
.
public enum TempatureUnit
{
Celcius,
Fahrenheit
}
И измените предыдущие классы и интерфейсы:
public interface ITemperatureConverter
{
int Convert(int source);
TempatureUnit SourceUnit {get;}
TempatureUnit TargetUnit {get;}
}
public class PlaceAndTemperature
{
public PlaceAndTempature(string name, int temperature, TempatureUnit unit)
{
Name = name;
Temperature = temperature;
TempatureType = unit;
}
public string Name { get; private set; }
public int Temperature { get; private set; }
public TempatureUnit TemperatureType {get; private set; }
public PlaceAndTemperature Convert(ITemperatureConverter converter)
{
return new PlaceAndTemperature(Name, converter.Convert(Temperature), converter.TargetUnit);
}
}
Собираем все вместе
Отлично. Не так много осталось. Давайте вернемся к исходному коду и обновим его:
public void Button1_Click(object source, EventArgs e)
{
var form = new PlaceAndTemptureForm();
var result = form.ShowDialog(this);
if (result != DialogResult.Ok)
return; // failed for some reason
var fahrenheit = form.GetPlaceAndTemperature();
var celcius = fahrenheit .Convert(new FahrenheitToCelciusConverter());
var form = new ResultForm();
form.SetTemperatures(fahrenheit, celsius);
resultDialog.ShowDialog(this);
}
Основная информация
Есть еще кое-что, что вам нужно исправить самостоятельно. Как создание FahrenheitToCelciusConverter. Начните с чего-то вроде:
public class FahrenheitToCelciusConverter : ITemperatureConverter
{
public int Convert(int source)
{
// put your code here
}
public TempatureUnit SourceUnit {get { return TemperatureUnit.Fahrenheit; }}
public TempatureUnit TargetUnit {get { return TemperatureUnit.Celcius; }}
}
Вам также нужно будет создать форму результата или просто обновить основную форму.