среда, 2 апреля 2008 г.

Типизированный WPF data binding

Я уже писал, что реализацию датабайдинга в WPF нельзя назвать элегантной. В связи с этим, я начал размышляя на тему, как бы скрыть всю эту нетипизированность и конверторы. В новой версии C# у нас же есть lambda expression и AST, т.е. есть возможность вытаскивать имена свойств (и даже цепочки свойств) в типизированном виде. Вот что получилось на текущий момент.
В качестве примера я взял преобразование над парой свойств FirstName и LastName. На форме два поля и ниже выводится FirstName+LastName большими буквами

Вот как это выглядит в коде



Все типизировано и без конвертора

В дальнейшем будет возможность указывать не DependencyProperty, а просто свойство контрола, как-то так


В случае одного свойства промежуточный класс не нужен, и будет совсем просто


Работающий код можно посмотреть здесь

суббота, 16 февраля 2008 г.

Упростить выражение в OnTypedInit

Теперь у нас типизированный sender, поэтому, скорее всего, получится сделать так, чтобы можно было писать более кратко
binder.Add(() => sender.Text, x => x.Name);
вместо
iderBinder.Add(sender).Add(x => x.Text, x => x.Name);
Предполагается это сделать через проход по Expression, чтобы выделить sender. Конечно, это накладывает сильные ограничения на используемые лямбда-выражения. Проверка допустимости лямбда-выражения будет осуществляться, естественно, только в рантайме, это недостаток. Но на это можно пойти из-за упрощения синтаксиса часто используемых выражений.

Новая версия

Выкладываю новую версию.

Теперь в OnInit-е не надо кастить sender
((TextBox)sender)...
Поробнее см. в ответе на сообщение krasin-у.

Введено свойство DataFunc. Теперь экземпляр объекта с данными передается через DataFunc вместо аргументов методов ToModel, FromModel. Перерь можно выделить отдельный интерфейс с методами
ToModel();
FromModel();
Этот интерфейс не будет иметь generic параметра TData. Это позволит писать классы, которые будут вызывать байндинг, без параметра TData.

P.S. Надо позаботится о более удобном хранении версий, чем блог ;)

суббота, 12 января 2008 г.

Продолжение "Строго типизированная привязка данных для ASP.NET"

Надо реализовать возможность указывать не только непосредственно свойство типа x=>x.Name, но и цепочки типа x=>x.Address.City. При этом надо остслеживать то, что в цепочке может встретиться null, и тогда возвращать null. Такое поведение сейчас реализует метод Eval в ASP.NET. Это делается с помощью прохода по объекту Expression.

пятница, 11 января 2008 г.

Строго типизированная привязка данных для ASP.NET

Easier refactoring and exploration. ... Both lend themselves to having a more manageable code base over time.


Аннотация
Предлагается механизм строго типизированной привязки данных с помощью C#(VB) кода. Новый синтаксические конструкции языка C# 3.0 (такие как вывод типа, лямбда выражения, методы расширения) сделали данный подход более элегантным. Механизм привязки данных не накладывает ни каких ограничений на framework, который используется для работы с данными.


Ведение

Место положение привязки данных показано на рисунке.

С одной стороны у нас есть контролы, в которых инкапсулирована логика представления и взаимодействия с пользователем. С другой стороны объекты с данными. Привязка данных выполняет две операции:

  • перенос данных из объектов на страницу (чаще всего в контролы)
  • перенос данных со страницы в объекты данных

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

P1. Как декларируется привязка данных? (Место, где пишутся выражения привязки данных. Язык выражений.).
P2. Кто и на каком этапе жизненного цикла страницы выполняет код привязки?

В предлагаемом подходе для пункта P1 используются лямбда выражения или реже классы. Для выполнения пункта P2 предлагаются два метода FromModel и ToModel. Данный подход не определяет, когда будет выполнятся код привязки данных, тем самым оставляя возможность разработки для пункта P2 специализированных классов.

Схема привязки данных

На странице определяется одно или несколько полей типа, который реализует интерфейс IGroupBinder<Tdata>. Параметр TData указывает на тип объекта данных.
private GroupBinder<Customer> customerBinder;
Эти поля обычно инициализируются в конструкторе формы или в методе Page_Init.

Привязка контролов

Если контрол расположены непосредственно на форме, то Visual Studio генерирует поле класса формы, которое можно использовать в code behind. Привязку данных можно декларировать в методе Page_Init.

protected void Page_Init(object sender, EventArgs e)
{
customerBinder.Add(TextBox1).Text(x => x.Name);

Если контрол расположен внутри template-а, то привязка данных осуществляется через обработчик события Control.Init. В markup-е подписываемся на событие

<asp:TextBox runat="server" OnInit="TextBox3_OnInit" />

В code behind-е декларируем привязку данных

protected void TextBox3_OnInit(object sender, EventArgs e)
{
customerBinder.Add((TextBox)sender).Text(x => x. Name);
}

Декларирование привязки в markup-е


Для контролов таких как Repeater внутри template-а можно указывать приязку данных, используя ASP.NET синтаксис

<asp:Label runat="server" Text="<%# customerBinder.Data.Address %>" />

Реализацию и примеры использования можно посмотреть здесь.