Использование XML и LINQ в элементах управления TreeView и ListView - Редактирование информации
ОГЛАВЛЕНИЕ
Редактирование информации
ASP.NET включает в себя множество инструментов для отображения и редактирования XML-документов. Предыдущая статья по теме отображения информации демонстрировала способ создания веб-страницы, отображающей содержимое иерархического XML-файла при помощи элементов управления TreeView, ListView, XmlDataSource, LinqDataSource и примерно 50 строк кода. В частности, страница отображала содержимое фиктивной телефонной книжки с номерами сотрудников, которая позволяла хранить неопределенное число сотрудников, вложенных в отделы и филиалы компании. Элементы управления TreeView и XmlDataSource отображали различные филиалы и отделы, в то время как ListView и LinqDataSource отображали сотрудников, принадлежащих к выбранному отделу или филиалу.
В дополнение к отображению информации ListView и LinqDataSource могут быть расширены таким образом, чтобы они поддерживали редактирование, вставку и удаление информации. Данная статья исследует способ обновления ListView и кода, тем самым позволяя посетителям добавлять, редактировать и удалять записи о телефонах сотрудников. Результатом данной статьи будет веб-страница, которая отображает XML-информацию и позволяет пользователю обновлять ее из простого, легкого в использовании, интерфейса веб-страницы. Читайте далее, чтобы узнать больше об этом!
Настройка ListView для поддержки редактирования
Элемент управления ListView, предоставленный в ASP.NET версии 3.5, отображает серию записей из источника данных при помощи шаблонов. В дополнение к выводу информации элемент управления ListView также может быть использован для вставки, редактирования и удаления информации. Как и элемент GridView, элемент управления ListView позволяет редактирование "по месту". То есть, пользователь может выбрать определенную запись на редактирование из отображенного списка записей, выполнить все необходимые изменения и затем обновить информацию. ListView также предоставляет функциональность вставки.
Принципы редактирования записей в ListView просты. Нам необходимо создать специальный шаблон для редактируемого элемента - данный шаблон, EditItemTemplate, используется для обработки элемента, редактируемого пользователем. В дополнение к этому нам необходимо добавить элемент управления Button, LinkButton или ImageButton (обычно в ItemTemplate), у которого свойство CommandName установлено в "Edit". При нажатии на данную кнопку выполняется постбэк и ListView повторно привязывается к своему источнику данных, при этом данный элемент обрабатывается при помощи EditItemTemplate.
ItemTemplate достаточно прост - просто добавьте LinkButton (Button или ImageButton) со свойством CommandName установленным в "Edit":
<ItemTemplate>
<tr>
<td>
<asp:LinkButton ID="lnkEdit" runat="server" CommandName="Edit" Text="Edit" />
</td>
<td>
<%# Eval("Name") %>
</td>
<td>
<%# Eval("Telephone") %>
</td>
</tr>
</ItemTemplate>
До того как мы создадим EditItemTemplate для ListView, существует усложняющее обстоятельство в нашей ситуации - нам необходим для начала адрес. Вспомните, ведь отображаемые в ListView записи могут быть расположены на разных "уровнях" в XML-файле (т.е. различных филиалах/отделах). К примеру, при выборе определенного филиала или отдела из TreeView, ListView отображает не только сотрудников данного филиала или отдела, но и всех сотрудников дочерних филиалов и отделов. Необходимо иметь возможность определить правильный филиал или отдел, которому принадлежит данный сотрудник, при сохранении измененных значений обратно в XML-файл.
Мы можем решить данную проблему путем запоминания адреса XPath XML-элемента Employee при загрузке его в ListView. Для этого нам необходимо добавить свойство в наш анонимный тип, возвращенный запросом LINQ. Текст в красном цвете XPathAddress: демонстрирует новый анонимный тип,
var query = from employeeElement in parentElement.Descendants("Employee")
select new
{
Name = employeeElement.Attribute("name").Value,
Telephone = employeeElement.Attribute("telephone").Value,
XPathAddress = getXPathAddress(employeeElement)
};
В дальнейшем мы установим данное значение в качестве свойства CommandArgument элемента LinkButton "Update" в EditItemTemplate элемента ListView.
Как вы можете заметить в указанном выше LINQ-запросе, XPathAddress было назначено значение, возвращенное методом getXPathAddress, которое нам необходимо создать в пределах класса с фоновым кодом ASP.NET-страницы. Метод итеративно пройдет по переданной структуре employeeElement к корневому элементу, тем самым выстраивая значение XPathAddress поднимаясь по дереву:
private string getXPathAddress(XElement element)
{
XElement cElement = element;
string xPath = "";
// Мы итеративно пройдемся по структуре к корневому элементу
// Цикл завершится в корневом элементе (мы не включаем корневой элемент
// в адрес!!)
while (cElement.Parent != null)
{
xPath = String.Format("/*[@id='{0}']",
cElement.Attribute("id").Value)
+ xPath;
cElement = cElement.Parent;
}
return xPath;
}
Теперь мы знаем выражение XPath для каждого объекта сотрудника и мы можем создать EditItemTemplate. Как вы могли бы уже заметить, свойству CommandArgument элемента LinkButton "Update" назначается значение XPathAddress , возвращенное LinqDataSource. Нам необходимо использовать данное значение в коде для обновления соответствующей записи сотрудника. Также обратите внимание на то, что вместо отображения значений имени и телефона сотрудника в Label мы используем веб-элемент управления TextBox.
<EditItemTemplate>
<tr>
<td>
<asp:LinkButton ID="lnkUpdate" runat="server"
CommandName="XUpdate"
CommandArgument="<%# Eval("XPathAddress") %>"
Text="Update" />,
<asp:LinkButton ID="lnkCancelEdit" runat="server"
CommandName="Cancel"
Text="Cancel" />
</td>
<td>
<asp:TextBox ID="txtEditName" runat="server"
Text="<%# Eval("Name") %>" />
</td>
<td>
<asp:TextBox ID="txtEditTelephone" runat="server"
Text="<%# Eval("Telephone") %>" />
</td>
</tr>
</EditItemTemplate>
Вам наверняка интересно, почему мы использовали значение CommandName "XUpdate" вместо "Update". Если мы установим CommandName в "Update", то ListView попробует обновить изменения, автоматически вызвав метод Update элемента управления источником данных. Мы сопоставили данные собственноручно (в обработчике события Selecting элемента управления LinqDataSource), так что наш LinqDataSource в данном случае не может служить в качестве обновляющего источника. Поэтому нам необходимо самим написать метод, чтобы сохранить изменения.