Сегодня мы добавим функциональность на страницу LanguageEdit.aspx, и сможем добавлять новые языки или редактировать уже существующие.
Для начала определим две переменные: одна будет представлять собой объект Language, который мы создали еще раньше с помощью ADO.NET Framework Entity, а вторая - собственно инструмент работы с БД - контекст:
private Language languageObject;
private DatabaseConnection context;
* This source code was highlighted with Source Code Highlighter.
Далее в обработчик загрузки страницы Page_Load добавим проверку на наличие id:
if (Request["id"] != null)
{
int id = 0;
int.TryParse(Request["id"], out id);
if (id != 0)
{
try
{
context = new DatabaseConnection();
var lan = from l in context.Language
where l.LanguageId == id
select l;
languageObject = (Language)lan.First();
}
catch
{
//log
}
}
}
if (languageObject == null)
{
languageObject = new Language();
}
if (!IsPostBack)
Page.DataBind();
* This source code was highlighted with Source Code Highlighter.
Логика работы этого блока проста: если мы получаем в качестве параметра id, то извлекаем из базы объект по этому id. Если же параметра нет, значит, мы хотим создать новый язык.
В обработчик события Unload можно добавить "уничтожение" объекта context.Dispose(), хотя, полагаю, ресурсы и так будут автоматически очищены по завершении обработки страницы.
Теперь разместим на странице наши контролы, для начала это буду два поля ввода - в одном заголовок языка, во втором его кодовое представление (например, "en-EN"), с его помощью удобно сразу выставлять региональные настройки. Позднее мы добавим контрол загрузки файла, с помощью которого будем грузить на сервер иконки с изображением флага, а пока надо разобраться с основными вещами.
Мы подошли к ключевому вопросу - привязка данных к форме. ASP.NET предлагает несколько контролов для привязки данных, но после некоторой возни с ним мне пришлось отказаться от их использования. Фактически, только два контрола - DetailsView и FormView - позволяют отображать данные по одному объекту, но мне так и не удалось заставить их привязываться к EntityObject. По какой-то, неведомой мне причине, эти контролы в качестве источника данных требуют обязательно объект, который наследут IListSource, IEnumerable, или IDataSource. Наш объект EntityObject не реализует ни один из этих интерфейсов. В качестве источника данных можно было бы использовать ObjectDataSource, но для этого нужно соблюсти определенные требования к классам доступа DAL - поскольку мы используем классы, сгенерированные EntityFramework, использование их не получается. Можно, конечно, было бы написать обертку к этим классам, но плодить лишний код не хочется совершенно.
После некоторых раздумий, а также просмотра обновленного кода проекта TheBeerHouse пришлось остановится на простой односторонней привязке данных к объекту. Что это значит? Очень просто - при открытии страницы мы создаем объект, а наши поля, привязанные к нему, заполняются автоматически. Когда мы хотим сохранить измененный объект, мы извлекаем содержимое полей вручную. Полагаю, ручное извлечение неизбежно - ведь объект еще не сохранен, а значит, поля невозможно привязать. Если кто подскажет более удачное решение, будет здорово.
Итак, создаем на странице простое свойство, которое имеет только метод get и возвращает наш объект:
protected Language LanguageObject
{
get
{
return languageObject;
}
}
* This source code was highlighted with Source Code Highlighter.
На страницу добавляем текстбоксы и осуществляем привязку, например:
<asp:TextBox ID="txtLangCode" runat="server"
Text="<%# LanguageObject.LanguageCode %>" Width="214px" />
* This source code was highlighted with Source Code Highlighter.
А теперь вернемся к первому коду, обратите внимание:
if (!IsPostBack)
Page.DataBind();
* This source code was highlighted with Source Code Highlighter.
Этот код проверяет, был ли постбэк, и, если нет, привязывает все контролы формы. Если мы будем делать привязку и после постбэка, то введенные нами данные в форму будут затерты извлеченными из объекта, что нам совсем не нужно.
Ну вот, осталось дело за малым: сохранить измененные данные. Кидаем на форму кнопку, добавляем событие Click и в обработчике пишем примерно такой код:
bool result = false;
try
{
if (context == null)
context = new PBPWebDatabaseConnection();
if (languageObject != null)
{
languageObject.LanguageTitle = Server.HtmlEncode(txtLangName.Text);
languageObject.LanguageCode = Server.HtmlEncode(txtLangCode.Text);
if (filePathToUpload != "")
languageObject.IconName = Path.GetFileName(filePathToUpload);
if (languageObject.LanguageId == 0)
context.AddObject("Language", languageObject);
int saved = context.SaveChanges();
if (saved == 1)
{
panelInfo.Activate(true, Messages.LanguageSaveOK, Messages.LabelLinkToLanguages, Pages.Languages);
Master.AddRedirect(Pages.Languages, 4);
panelMain.Visible = false;
result = true;
}
}
}
catch (Exception ex)
{
//log
}
if (!result)
panelInfo.Activate(false, Messages.LanguageSaveFail, string.Empty, string.Empty);
* This source code was highlighted with Source Code Highlighter.
Сначала мы проверяем, не нуль ли контекст. Если вдруг он равен null, создаем новый. Объект languageObject уже должен быть создан к этому времени (пустой или взятый из базы). Перезаписываем его свойства данными из полей формы. Затем, если объект был заново созданный (id у него равно 0), то добавляем в контекст. Если нет, ничего не делаем, потому что в этом случае объект уже привязан к контексту (это произошло, когда мы извлекали объект по id). Осталось просто сохранить объект и отреагировать на полученный результат.
Вроде ничего сложного. Если что непонятно, спрашивайте. А загрузку файлов мы чуть попозже обсудим.
Комментариев нет:
Отправить комментарий