Элементы управления источниками данных — это новый тип серверного элемента управления, представленный в Microsoft Visual Studio 2005. Они являются ключевой частью архитектуры привязки данных и могут обеспечивать модель декларативного программирования и автоматическое поведение привязки данных посредством элементов управления привязкой данных. В этой статье и последующих статьях этой серии будут представлены основные элементы реализации элементов управления источниками данных.
Введение
Короче говоря, элемент управления источником данных суммирует хранилище данных и некоторые операции, которые можно выполнить с содержащимися данными. Элемент управления DataBound связан с элементом управления источником данных через его свойство DataSourceID. Большинство традиционных хранилищ данных имеют табличную или иерархическую форму, и элементы управления источниками данных разделены соответствующим образом. Здесь мы хотим представить элемент управления источником данных в табличном формате.
Сам элемент управления источником данных мало что делает; вся логика инкапсулирована в классах, производных от DataSourceView. По крайней мере, один DataSourceView должен реализовать функцию получения (то есть ВЫБОРА) набора строк. Он может обеспечивать функцию изменения данных (т. е. ВСТАВКА, ОБНОВЛЕНИЕ и УДАЛЕНИЕ) (необязательно). Элементы управления с привязкой к данным могут проверять включенные наборы функций с помощью различных свойств Can???. Сам элемент управления источником данных — это просто контейнер для одного или нескольких представлений с уникальными именами. По соглашению доступ к представлению по умолчанию можно получить по его имени или оно может быть пустым. Существует ли связь между различными представлениями и какой тип связи, можно соответствующим образом определить на основе реализации каждого элемента управления источником данных. Например, элемент управления источником данных может предоставлять разные отфильтрованные представления одних и тех же данных в разных представлениях или может предоставлять набор вложенных строк во вторичном представлении. Вы можете использовать свойство DataMember элемента управления с привязкой к данным, чтобы выбрать определенное представление (если элемент управления источником данных предоставляет несколько представлений). Обратите внимание, что ни один из встроенных элементов управления источниками данных в Whidbey в настоящее время не поддерживает несколько представлений.
Наконец, позвольте мне представить немного контента. Элементы управления источниками данных (и их представления) реализуют два набора API. Первый набор API — это абстрактный интерфейс, определенный для четырех общих операций с данными, которые можно использовать обычным образом из любого элемента управления, связанного с данными. Вторая группа является необязательной, определяется в зависимости от представляемого ею домена или хранилища данных, обычно строго типизирована и предназначена для разработчиков приложений.
Пример
. В этих статьях вы реализуете источник WeatherDataSource, который будет работать с REST (английским) XML API, предоставленным сайтом Weather.com (английская версия), для получения информации о погоде на основе почтового индекса. Элементы управления производными источниками данных обычно реализуются в первую очередь.
публичный класс WeatherDataSource: DataSourceControl {
общедоступная статическая строка только для чтения
CurrentConditionsViewName = «CurrentConditions»;
частный WeatherDataSourceView _currentConditionsView
частный WeatherDataSourceView CurrentConditionsView {
;
получать {
если (_currentConditionsView == ноль) {
_currentConditionsView = новый WeatherDataSourceView (это, CurrentConditionsViewName);
}
вернуть _currentConditionsView;
}
}
общественная строка ZipCode {
получать {
строка s = (строка)ViewState["ZipCode"];
return (s != null) s: String.Empty;
}
набор {
если (String.Compare(значение, ZipCode,
StringComparison.Ordinal) != 0) {
ViewState["ZipCode"] = значение;
CurrentConditionsView.RaiseChangedEvent();
}
}
}
защищенное переопределение DataSourceView GetView (строка viewName) {
если (String.IsNullOrEmpty(viewName) ||
(String.Compare(viewName, CurrentConditionsViewName,
StringComparison.OrdinalIgnoreCase) == 0)) {
вернуть CurrentConditionsView;
}
выдать новое исключение ArgumentOutOfRangeException("viewName");
}
защищенное переопределение ICollection GetViewNames() {
вернуть новую строку [] { CurrentConditionsViewName };
}
общественная погода GetWeather() {
вернуть CurrentConditionView.GetWeather();
}
}
Как видите, основная идея состоит в том, чтобы реализовать GetView для возврата именованного экземпляра представления и GetViewNames для возврата набора доступных представлений.
Здесь выберите «Произвести из DataSourceControl». Нелегко заметить одну вещь: элемент управления, привязанный к данным, на самом деле ищет интерфейс IDataSource, а элемент управления DataSource реализует интерфейс, реализуя GetView и GetViewNames. Причина, по которой необходим интерфейс, заключается в том, чтобы позволить элементу управления источником данных быть как табличным, так и иерархическим (если возможно, в этом случае получить из основной модели и реализовать другую модель в качестве интерфейса). Во-вторых, это также позволяет преобразовывать другие элементы управления в различных сценариях, чтобы удвоить емкость источника данных. Также обратите внимание на общедоступное свойство ZipCode и метод GetWeather, который возвращает строго типизированный объект Weather. Этот API подходит для разработчиков страниц. Разработчикам страниц не нужно думать о DataSourceControl и DataSourceView.
Следующим шагом является реализация самого представления источника данных. Этот конкретный пример предоставляет только функциональность уровня SELECT (это минимальное требование и единственная функциональность, полезная в этом сценарии).
частный запечатанный класс WeatherDataSourceView: DataSourceView {
частный WeatherDataSource _owner
public WeatherDataSourceView (владелец WeatherDataSource, строка viewName)
: base(владелец, viewName) {
_владелец = владелец;
}
защищенное переопределение IEnumerable ExecuteSelect(
Аргументы DataSourceSelectArguments) {
аргументы.RaiseUnsupportedCapabilitiesError(this);
Погода WeatherObject = GetWeather();
вернуть новую погоду [] {weatherObject};
}
внутренняя погода GetWeather() {
строка zipCode = _owner.ZipCode;
если (zipCode.Length == 0) {
выбросить новое InvalidOperationException();
}
WeatherService WeatherService = новый WeatherService (zipCode);
вернуть WeatherService.GetWeather();
}
внутренняя пустота RaiseChangedEvent() {
OnDataSourceViewChanged(EventArgs.Empty);
}
}
По умолчанию класс DataSourceView возвращает значение false из таких свойств, как CanUpdate, и генерирует исключение NotSupportedException из Update и связанных методов. Единственное, что вам нужно сделать здесь, в WeatherDataSourceView, — это переопределить абстрактный метод ExecuteSelect и вернуть IEnumerable, содержащий «выбранные» данные о погоде. В реализации используется вспомогательный класс WeatherService, который просто использует объект WebRequest для запроса сайта Weather.com (на английском языке) с использованием выбранного почтового индекса (ничего особенного в этом нет).
Возможно, вы заметили, что ExecuteSelect помечен как защищенный. На самом деле элемент управления с привязкой к данным вызывает общедоступный (и запечатанный) метод Select, передаваемый в обратном вызове. Реализация Select вызывает ExecuteSelect и вызывает обратный вызов с результирующим экземпляром IEnumerable. Эта закономерность очень странная. Для этого есть причина, которая будет объяснена в последующих статьях этой серии. Пожалуйста, подождите...
Вот пример такого использования:
Почтовый индекс: <asp:TextBox runat="server" id="zipCodeTextBox" />
<asp:Button runat="server" onclick="OnLookupButtonClick" Text="Look" />
<hr />
<asp:FormView runat="server" DataSourceID="weatherDS">
<Шаблон предмета>
<asp:Label runat="сервер"
Text='<%# Eval("Температура", "Текущая температура — {0}.") %>' />
</ItemTemplate>
</asp:FormView>
<nk:WeatherDataSource runat="server" id="weatherDS" ZipCode="98052" />
<script runat="server">
Private void OnLookupButtonClick (отправитель объекта, EventArgs e) {
WeatherDS.ZipCode = zipCodeTextBox.Text.Trim();
}
</script>
Этот код устанавливает почтовый индекс в ответ на ввод пользователя, что приводит к тому, что источник данных выдает уведомление об изменении, в результате чего связанный элемент управления FormView выполняет привязку данных и изменяет отображение.
Теперь код доступа к данным инкапсулирован в элементе управления источником данных. Кроме того, эта модель позволяет Weather.com (на английском языке) публиковать компонент, который также может инкапсулировать детали, специфичные для его услуги. Надеюсь, это сработает. Кроме того, абстрактный интерфейс источника данных позволяет FormView работать только с данными о погоде.
В следующей статье вы улучшите элемент управления источником данных, чтобы автоматически обрабатывать изменения значения фильтра (то есть почтового индекса), используемого для запроса данных.