пятница, 16 января 2015 г.

Winforms and databings. Advanced options

Это отчасти продолжение предыдущего. Но мне явно не хватает компетенции и решительности поставить в вопросе точку.

Шаг 6. Украшение

Данные привязались и успешно отображаются и обновляются. Теперь мне нужно, чтобы они отображались красиво.
Взять те же даты. Или вот углы... да, абсолютно отвратительные углы в радианах.

textbox1.DataBindings.Add("Text", CurrentFotoConf.AppObj, "Alpha", true, DataSourceUpdateMode.OnPropertyChanged)

Которые пользователю хотелось бы видеть в градусах. И округленными до второго знака. Значит нам нужно форматирование. Если мы собираемся модифицировать исходные данные, то нам нужен еще и парсер ввода (который будет переводить пользовательские градусы, обратно в радианы).
У класса Binding (экземпляр которого мы тут неявно создаем), есть два события для этих случаев: Format и Parse (тип события ConvertEvent...). Их нам и надо обработать.

Залезть в этот экземпляр привязкм можно совершенно по-хамски:
textbox1.DataBindings[0].Format += ...

Но можно и по-человечески:
Binding b = new Binding("Text", CurrentFotoConf.AppObj, "Alpha", true, DataSourceUpdateMode.OnPropertyChanged);
b.Format += new ConvertEventHandler(...);
b.Parse += new ConvertEventHandler(...);


Внимание, вопрос: и где мне разместить мои обработчики?.. Можно здесь же, на этой форме - но это не очень рационально: они наверняка понадобятся где-то еще. Поэтому, я сделала так:

public static class Converters
{
   public static void RadToGradFormat(object sender, ConvertEventArgs e)
   {
      if (e.DesiredType != typeof(string))
         return;

      e.Value = Math.Round(Measures.RadToGrad(Convert.ToDouble(e.Value)), 2);
   }

   public static void GradToRadParse(object sender, ConvertEventArgs e)
   {
      if (e.DesiredType != typeof(double))
         return;

      e.Value = Math.Round(Measures.GradToRad(Convert.ToDouble(e.Value)));
   }
}
...
b.Format += new ConvertEventHandler(Converters.RadToGradFormat);
b.Parse += new ConvertEventHandler(Converters.GradToRadParse);

Где, класс Measures - это такой же статический класс позволяющий мне конвертировать много разных форматов представления. А Math - стандартный класс С#. По аналогии с которым я и выбрала это решение, хотя, полагаю есть более изящный способ.

Шаг 7. Бесконечный путь к совершенству или размышления, которые стоит не забыть до понедельника.

Сейчас мои привязки данных выглядят так:


Binding b = new Binding("Text", CurrentFotoConf.AppObj, "Betta", false, DataSourceUpdateMode.OnPropertyChanged);
b.Format +=new ConvertEventHandler(Converters.RadToGradFormat);
b.Parse += new ConvertEventHandler(Converters.GradToRadParse);
this.AcrossTB.DataBindings.Add(b);
b = new Binding("Text", CurrentFotoConf.AppObj, "Alpha", false, DataSourceUpdateMode.OnPropertyChanged);
b.Format += new ConvertEventHandler(Converters.RadToGradFormat);
b.Parse += new ConvertEventHandler(Converters.GradToRadParse);
this.AlignTB.DataBindings.Add(b);


А я размышляю, что это тоже не слишком читаемо и было бы, наверное, круто, сделать что-то вроде:



this.AcrossTB.DataBindings.Add(CurrentFotoConf.AppObj.BindBetta("Text"));
this.AlignTB.DataBindings.Add(CurrentFotoConf.AppObj.BindAlpha("Text"));

или даже так

CurrentFotoConf.AppObj.BindBetta(this.AcrossTB, "Text");
CurrentFotoConf.AppObj.BindAlpha(this.AlignTB, "Text");
CurrentFotoConf.BindConfName(this.ConfNameTB, "Text");

Чnо будет достаточно круто в соответствии с упомянутой ниже книгой.  Т.е. в рамках читаемости общей ветки.
Но я не уверена, что создание таких методов не усложниn исходные классы сверхмеры. Тем более, что мое чувство упорядоченности требует тогда уж, создать такие методы для всех полей моих отображаемых классов. Но даже если я с ним договорюсь, остается некий шанс, что для некоторый шанс, что мне, внезапно, для какого-нибудь из свойств будут нужны разные настройки форматирования... создавать тогда два метода?..

А еще... еще можно было бы создать уже четвертый (верхний я вам не показала :p) уровень наследования и классы вроде:


class FotoConfView : FotoConf
{
...
}

и засовывать все эти штуки в него.  Хотя это уже откровенно плохая идея: создавать класс, чтобы свалить в него несортированный (заранее известно, что несортированный!) функциональный мусор.

Или... (о, эти безграничные возможности) я могу выполнять преобразования в моих { set; get; }. Но, это сильно ограничит меня, поскольку... как же мне тогда для вычислений получить нужные мне радианы?..


Комментариев нет:

Отправить комментарий