#asp.net #web
Вопрос:
Я создал функцию поиска с использованием представления сетки, программа считывает вводимые пользователем данные и на основе этого возвращает данные, соответствующие базе данных, однако возвращает всю строку, которая включает 2 столбца идентификаторов, которые я не хочу показывать. Звучит как что-то простое, но я, кажется, не могу найти никакого руководства о том, как это сделать.
Кроме того, во второй колонке IdCargo
(IdProfession, на английском языке) я хотел бы перевести эти данные, например, если должен появиться конкретный идентификатор, я хотел бы вместо этого показать профессию указанного сотрудника. Я также хотел бы показать колонку с названием «Груз» вместо «IdCargo», также вместо «CargaHoraria» я хочу показать «Carga Horaria».
Если кто-нибудь знает какое-либо руководство или учебник по использованию GridViews и SQL, это было бы чрезвычайно полезно и для будущих исследований.
Ответ №1:
Здорово. Хорошо, нам не нужно сильно беспокоиться о части поиска — я предположу, что вы введете какой-то поиск с параметрами, результатом будет таблица данных.
Теперь я НАСТОЯТЕЛЬНО рекомендую вам рассмотреть представление списка вместо представления сетки.
Что касается управления какими колонками? Ну, вы можете создать шаблон для каждой колонки. (и именно поэтому я предлагаю просмотр списка — это меньше разметки).
Однако у меня не слишком много столбцов — так что GV «в порядке», но если вам нужно больше столбцов, больше пользовательского макета — тогда LV будет МЕНЬШЕ разметки.
And another REALLY big advantage of LV, is you can get it to write the markup for you.
Anyway, ok, this is our GV.
VERY important: We have a PK primary key for each row («ID»). And we of course don’t want to show or display that PK ID, but as we all know, a PK is the lifeblood of any data system. So, there is a VERY cool feature in GV — called DataKeys. It allows you to use/have/play the PK row id, but NEVER do you have to expose or display it in the GV. (so not only nice from UI point of view, also VERY nice from a security point of view).
So, say we have this GV layout:
lt;div style="width:40%;padding:25px"gt; lt;stylegt; .borderhide input {border:none}lt;/stylegt; lt;asp:GridView ID="GVPeople" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" cssclass="table borderhide"gt; lt;Columnsgt; lt;asp:TemplateField HeaderText="First Name"gt; lt;ItemTemplategt; lt;asp:TextBox ID="FirstName" runat="server" Text='lt;%# Eval("FirstName") %gt;' gt;lt;/asp:TextBoxgt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt; lt;asp:TemplateField HeaderText="Last Name"gt; lt;ItemTemplategt; lt;asp:TextBox ID="LastName" runat="server" Text='lt;%# Eval("LastName") %gt;' gt;lt;/asp:TextBoxgt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt; lt;asp:TemplateField HeaderText="City"gt; lt;ItemTemplategt; lt;asp:TextBox ID="City" runat="server" Text='lt;%# Eval("City") %gt;' gt;lt;/asp:TextBoxgt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt; lt;asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center"gt; lt;ItemTemplategt; lt;asp:CheckBox ID="Active" runat="server" Checked='lt;%# Eval("Active") %gt;'/gt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt; lt;asp:TemplateField HeaderText="Hotel ID"gt; lt;ItemTemplategt; lt;asp:TextBox ID="Hotel_ID" runat="server" Text='lt;%# Eval("Hotel_ID") %gt;' gt;lt;/asp:TextBoxgt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt; lt;/Columnsgt; lt;/asp:GridViewgt;
And we will feel this GV with data — MANY more columns exist — but we don’t care.
so, my code so far is this:
Dim rstData As New DataTable Dim rstHotels As New DataTable ' for combo box Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not IsPostBack Then LoadGrid() ViewState("rstData") = rstData Else rstData = ViewState("rstData") End If End Sub Sub LoadGrid() rstHotels = MyRst("SELECT ID, HotelName from tblHotels ORDER BY HotelName") rstData = MyRst("SELECT * from People Order by FirstName") GVPeople.DataSource = rstData GVPeople.DataBind() End Sub
So now we have this:
Итак, ваша часть вопроса заключается в том, что мы явно не хотим показывать идентификатор Hotel_id, но хотим перевести его в описание. И, конечно, если мы собираемся разрешить изменения, то давайте преобразуем идентификатор Hotel_ID в поле со списком (выпадающий список). И, как и в поле со списком «Большинство/все», мы будем хранить идентификатор PK отеля, но, конечно же, для удобства использования отобразим название отеля.
Итак, вместо hotel_id мы меняем нашу разметку на эту:
lt;asp:TemplateField HeaderText="Hotel ID"gt; lt;ItemTemplategt; lt;asp:DropDownList ID="cboHotel" runat="server" DataTextField="HotelName" DataValueField="ID"gt; lt;/asp:DropDownListgt; lt;/ItemTemplategt; lt;/asp:TemplateFieldgt;
Хорошо, теперь нам нужно заполнить настроить поле со списком. У нас есть ДВЕ задачи:
Заполните поле со списком источником данных
Установите в поле со списком значение ТЕКУЩЕГО выбора для каждой строки gv.
Для этого мы будем использовать событие привязки данных к строке GV.
Итак, наш код для заполнения комбинации будет выглядеть следующим образом:
Итак, у нас есть этот код:
Protected Sub GVPeople_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GVPeople.RowDataBound If e.Row.RowType = DataControlRowType.DataRow Then ' get full row of data bind - all columns Dim gData As DataRowView = e.Row.DataItem ' NOT A GRID VIEW ROW!!!!! ' get combo box Dim cboHotels As DropDownList = e.Row.FindControl("cboHotel") ' setup cbo data source cboHotels.DataSource = rstHotels cboHotels.DataBind() cboHotels.Items.Insert(0, New ListItem("", "")) ' add blank (no choice) If IsDBNull(gData("Hotel_id")) = False Then cboHotels.SelectedValue = gData("Hotel_ID").ToString End If End If End Sub
итак, теперь наши результаты таковы:
Хорошо, это решает один из ваших вопросов/проблем.
Далее нужно отредактировать — и это ДЕЙСТВИТЕЛЬНО круто и ОЧЕНЬ просто.
Хорошо, если вы присмотритесь, я «скрою» границы текстовых полей, но теперь вы обнаружите, что можете перемещаться по вкладкам, как в Excel. И хорошая бесплатная пчелка заключается в том, что, когда текстовые поля имеют фокус, они отображаются!!
Итак, давайте опустим нашу кнопку под сеткой, чтобы сохранить изменения. Это выглядит так, когда я смотрю вокруг:
Очень похоже на волшебство — теперь вы можете перемещаться по вкладкам — почти как в Excel. И вы можете выбрать значение поля со списком.
И выше, мы опустили простую кнопку под GV, как это:
lt;/asp:GridViewgt; lt;asp:Button ID="cmdSave" runat="server" Text="Save Edits" CssClass="btn" /gt;
Хорошо, теперь нажмите кнопку сохранить данные.
Мы напишем одну вспомогательную процедуру. Существует множество причин для разделения этого кода на две подпрограммы. Итак, первая процедура?
Он отправит значения сетки ОБРАТНО в нашу таблицу. Если присмотреться, я сохранил источник данных таблицы GV в качестве rstData.
Таким образом, эта процедура отправляет сетку обратно в таблицу.
Sub GridToTable() ' pull GV rows back to table. For Each gRow As GridViewRow In GVPeople.Rows ' Get database PK value Dim PK As Integer = GVPeople.DataKeys(gRow.RowIndex).Item("ID") Dim OneDataRow As DataRow = rstData.Select("id = " amp; PK)(0) OneDataRow.Item("FirstName") = CType(gRow.FindControl("FirstName"), TextBox).Text OneDataRow.Item("LastName") = CType(gRow.FindControl("LastName"), TextBox).Text OneDataRow.Item("City") = CType(gRow.FindControl("City"), TextBox).Text OneDataRow.Item("Active") = CType(gRow.FindControl("Active"), CheckBox).Checked ' combo box Dim cboHotel As DropDownList = gRow.FindControl("cboHotel") If cboHotel.Text = "" Then OneDataRow("Hotel_ID") = DBNull.Value Else OneDataRow("Hotel_ID") = cboHotel.SelectedItem.Value End If Next End Sub
Ok, so now all we have to do is send the rstData table (and get this: this will handle NEW rows, or edits!!!!).
so, now our save button code looks like this:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click GridToTable() Using conn As New SqlConnection(My.Settings.TEST4) Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn) Dim da As New SqlDataAdapter(cmdSQL) Dim daC As New SqlCommandBuilder(da) conn.Open() da.Update(rstData) End Using End Using End Sub
So note how we send the WHOLE grid back to the database, and all changes in ONE shot.
Last but not least:
I used a helper routine to get a data table (became REAL fast typing that kind of code over and over, so I have this and I made it global to the whole application:
Public Function MyRst(strSQL As String) As DataTable Dim rstData As New DataTable Using conn As New SqlConnection(My.Settings.TEST4) Using cmdSQL As New SqlCommand(strSQL, conn) conn.Open() rstData.Load(cmdSQL.ExecuteReader) rstData.TableName = strSQL End Using End Using Return rstData End Function
ОБРАТИТЕ внимание, очень осторожно, я также ВСТАВЛЯЮ инструкцию sql в первую.Имя таблицы. Имя таблицы на самом деле не используется, но теперь, когда я сохранил SQL для этой таблицы?
Тогда на самом деле эта строка
Using conn As New SqlConnection(My.Settings.TEST4) Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn)
становится:
Using conn As New SqlConnection(My.Settings.TEST4) Using cmdSQL As New SqlCommand(rstData.TableName, conn)
Это означает, что если/когда у меня есть, скажем, дочерний мастер или несколько таблиц данных для редактирования на странице? Я использую набор данных (набор таблиц), у adn есть ОДИН маршрут для отправки всех таблиц и всех изменений обратно в базу данных одним выстрелом / процедурой. У нас нет более одной таблицы данных для редактирования, но это объясняет, почему я вставляю инструкцию SQL в имя таблицы данных «таблица», поскольку, как вы можете видеть, нам даже не нужно повторно вводить используемый sql.
ПРИМЕЧАНИЕ К ВАШЕМУ СВЕДЕНИЮ: Этот оператор sql, который я использовал для:
SELECT * from People WHERE ID = 0
Не был типом-о. Я использовал это, чтобы позволить SqlCommandBuilder выполнить всю грязную работу по подключению и созданию инструментов вставки и обновления sql для меня.
Комментарии:
1. Не будет никакого gridview намного сложнее, чем этот, это очень простой веб-сайт для школы, плюс мне нравится, как gridview выглядит лучше. Кроме того, я нашел статью о представлении сетки, поэтому мне удалось изменить название колонок, единственное, что я еще не понял, — это как «перевести» идентификаторы в то, что они представляют
2. Что ж, смотрите мое редактирование — это субботняя пицца — но я опубликую ПОСЛЕДНИЙ бит и НЕБОЛЬШОЙ код, чтобы показать, как мы можем отправить изменения сетки обратно с помощью простого простого кода. Так что через 15 минут или около того, я вернусь, чтобы закончить следующий бит кода. Но опубликованный код показывает, как я перевел значения в поле со списком
3. Кроме того, не стесняйтесь спрашивать код c# — для меня это не имеет большого значения (но код VB требует меньше усилий из-за большого количества автоматического литья, которое дает vb).
4. Хорошо, смотрите последнюю часть и обновите. Обратите внимание, насколько прост код для отправки ВСЕЙ таблицы изменений обратно в базу данных за ОДИН раз.