Советы по созданию динамического элемента управления «Расширенный поиск» в ASP.NET - PullRequest
6 голосов
/ 10 сентября 2009

альтернативный текст http://img3.imageshack.us/img3/1488/advancedsearch.png

Я создаю интерфейс «Расширенный поиск» в приложении ASP.NET. Мне не нужно SO, чтобы написать эту вещь для меня, но я застрял на конкретной проблеме, касающейся динамических элементов управления и ViewState. Я хотел бы получить некоторые указания о том, как подойти к этому. Вот моя ситуация:

Состав:

  • Обслуживаемый набор объектов API, представляющих сущности, поля и поиски, который обрабатывает построение поиска, генерацию SQL и возврат результатов. Так что обо всем позаботимся.
  • ASP.NET 3.5

Требуемая функциональность интерфейса:

(1) При начальной загрузке страницы интерфейс получает предварительно настроенный объект поиска с набором объектов SearchCriterion. Он связывает их в набор элементов управления (см. Изображение выше.)

  • Некоторые элементы поиска проще, например:

    Поле (DropDownList) | Оператор (DropDownList) | Значение (TextBox)

  • Элементы управления критериями поиска для некоторых типов полей содержат важную информацию, хранящуюся в состоянии просмотра, например:

    Поле (DropDownList) | Оператор (DropDownList) | Значение (DropDownList), где выпадающий список «Значение» заполняется запросом к базе данных.

  • Некоторые поля являются поисками для других сущностей, что вызывает цепочку селекторов полей, например:

    Поле (DropDownList) Поле (DropDownList) | Оператор (DropDownList) | Значение

(2) Пользователь изменяет поиск:

  • Добавление и удаление критериев поиска нажатием соответствующих кнопок
  • Настройка существующих критериев путем изменения поля, оператора или значения. Для изменения поля или оператора потребуется переконфигурировать элемент управления путем изменения доступных операторов, изменения элемента управления вводом «Значение» на другой тип или добавления / удаления DropDownLists из раздела «Поля», если поля типа поиска выбраны / не выбраны .

(3) Наконец, пользователь нажимает «Поиск», чтобы увидеть свои результаты.

Проблема:

Как вы, вероятно, уже знаете, отвечаете ли вы на этот вопрос, элементы управления, динамически добавляемые на страницу, исчезают при обратной передаче. Я создал UserControl, который управляет коллекцией элементов управления и аккуратно выполняет шаг (1) выше, как вы можете видеть на прикрепленном изображении. (Я не беспокоюсь о стиле на данный момент, очевидно.)

Однако в Postback все элементы управления исчезли, а мой объект API поиска пропал. Если бы я мог заставить динамически сгенерированную коллекцию элементов управления просто играть хорошо и придерживаться ViewState, я мог бы изучить элементы управления при обратной передаче, перестроить объект поиска, а затем аккуратно обработать события элемента управления.

Возможные решения

  • Я мог бы сделать объект поиска сериализуемым и сохранить его в viewstate. Затем при загрузке страницы я мог бы взять ее и восстановить коллекцию элементов управления во время загрузки страницы. Однако я не уверен, будет ли это хорошо работать с элементами управления, генерирующими события, и что произойдет с состоянием представления раскрывающихся списков, которые содержат данные из базы данных - могу ли я получить их обратно? Мне крайне нежелательно повторно запрашивать базу данных при каждой обратной передаче.

  • Я мог бы разработать собственный серверный элемент управления ( см. Эту ссылку ) для такого рода вещей ... но это новая тема для меня и потребует некоторого изучения, плюс я Я не совсем уверен, будет ли пользовательский серверный элемент управления работать с нефиксированными коллекциями элементов управления. Кто-нибудь знает об этом?

  • Я думал, что смогу сделать это, используя элементы управления с привязкой к данным - например, я могу привязать свою коллекцию критериев к повторителю, у которого есть фиксированная коллекция элементов управления (возможно, скрыть неиспользуемые элементы управления «значение» используйте внутренний повторитель для раскрывающихся списков "Поле"). Тогда вся информация останется во ViewState ... верно?

  • Любые новые идеи будут с благодарностью.

спасибо за вашу помощь. b.Fandango

Ответы [ 4 ]

4 голосов
/ 11 сентября 2009

Я занимался программированием около дня, и у меня получилось прекрасно работать, используя третий вариант, который я предложил в своем вопросе - элементы управления старой школы. На самом деле, я думал об этой идее, только когда был вынужден подробно написать вопрос - разве это не случается с вами все время?

Я поместил свой SearchCriterionControl в asp: Repeater и привязал его к своей коллекции объектов. Для Field Chooser я поместил asp: DropDownList во вложенный asp: Repeater и привязал к нему массив Field. Все работает прекрасно, сохраняет состояние, на самом деле требуется очень мало кода. Поэтому мне никогда не приходилось динамически добавлять элементы управления на страницу, слава богу.

Спасибо за ваши предложения, Эндер, Мэтт и ЭндрюВинн.

2 голосов
/ 10 сентября 2009

Я не могу предоставить вам точные шаги, которые вам нужно будет сделать, но я НАСТОЯТЕЛЬНО рекомендую изучить жизненный цикл страницы asp.net. Я создал пользовательский элемент управления как DLL один раз. Мне пришлось собирать данные обратной передачи на определенных этапах жизненного цикла, а затем заново создавать и связывать данные на других этапах. Кроме того, такие пометки, как viewstate, доступны только в определенных точках. Я знаю, что мне пришлось переопределить On_init, On_prerender и некоторые другие методы.

Извините, я не могу помочь, но у меня нет кода (со старым работодателем). Надеюсь, это поможет.

2 голосов
/ 10 сентября 2009

Если вы динамически добавляете элементы управления в дерево элементов управления, вам также необходимо добавить их в postpack. Просто вызовите метод, который создает элемент управления на Page_Load или Page_Init, и элементы управления должны остаться на странице при обратной передаче.

2 голосов
/ 10 сентября 2009

Поскольку в течение 2 часов никто больше не наносил удар, я скину свою шляпу в кольцо с решением, которое вообще не зависит от viewstate (или модели обратных передач ASP.NET).

Что если вы захватили все входные значения с помощью jQuery и вместо постбэка сделали пост на странице (или на новой странице results.aspx)? Или вы можете сделать все это асинхронным и выполнить Ajax-запрос к веб-методу, получить результаты и заполнить его на стороне клиента по мере необходимости?

Прискорбно, что вы должны восстановить, какой тип элементов управления использовался для построения поискового запроса, так как эти данные не будут передаваться с состоянием просмотра. Но я предполагаю, что вам все равно придется выполнить какой-то перевод ваших входных данных в форму запроса.

Прочтите здесь для получения дополнительной информации об использовании jQuery для обращения к методу страницы ASP.NET. Помните - методы страницы должны быть статическими (это просто упустить).

Я не уверен, что вы делаете на стороне сервера для создания вашего запроса - но я бы настоятельно рекомендовал LINQ. Ранее я выполнял аналогичную функцию «расширенного поиска», и после нескольких разных попыток обнаружил, что LINQ был прекрасным инструментом для решения этой проблемы, независимо от того, выполнял ли я запуск SQL с помощью LINQtoSQL или просто набор объектов в памяти.

Это сработало очень хорошо, потому что 1) LINQ - это отложенное выполнение и 2) запрос LINQ возвращает другой запрашиваемый объект. Здесь подразумевается, что вы можете объединять ваши запросы LINQ вместе, когда вы создаете их из своего ввода, вместо того, чтобы выполнять перевод одного массивного предложения в SQL или любой другой используемый вами бэкстор (одна из моих попыток заключалась в создании предложений SQL со строками, но все еще передавая входные данные через SQLParameters для защиты SQL-инъекций - это было грязно и сложно, когда созданный вручную LINQ был на порядок проще для понимания и реализации).

Например:

List<string> data; // or perhaps your a DB Context for LINQtoSQL?

var query = data.Where(item => item.contains("foo"));

if( {user supplies length search option} )
    query = query.Where(item => item.Length < 5);

// etc, etc.

// LINQ doesn't do anything until the query is iterated, at which point
// it will construct the SQL statement without you worrying about details or parameter binding
foreach(string value in query)
    ; // do something with the results

Из-за отложенного выполнения и запрашиваемого возвращаемого типа вы можете объединять запросы LINQ к этому выражению в течение всего дня и позволить ему беспокоиться о деталях реализации (таких как преобразование в запрос SQL) во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...