Управление повторителем - Отмена привязки для определенного элемента - PullRequest
7 голосов
/ 08 февраля 2010

Есть ли способ отменить привязку определенных элементов перед отображением страницы в элементе управления повторителем?

В настоящее время у нас есть коллекция элементов, привязанных к повторителю, и если элемент не является частью текущего языка, мы скрываем элемент.

Я хочу иметь возможность подсчитать ретранслятор и получить верный номер. Подсчет, который также не включает скрытые предметы.

Возможно ли отменить привязку определенных предметов, возможно, в событии ItemDataBound?

Обновление

Для каждого элемента в коллекции, которую мы связываем, мы проверяем базу данных во время ItemDataBound для получения дополнительной информации об элементе, такой как язык и т. Д. В настоящее время мы не можем отфильтровать связанные данные перед их привязкой. 1015 *

Ответы [ 4 ]

3 голосов
/ 08 февраля 2010

Более подходящим решением может быть фильтрация связанной коллекции, если в этих скрытых элементах нет особой необходимости. Что-то вроде

items.Where(i => i.IsInLanguage(currentLanguage));

Обновление:

Что касается меня, я бы использовал этот подход:

var items = db.
      Where(i => i.IsInLanguage(currentLanguage)).
      Where(i => i.SomeField == anotherFilterParameter);

repeater.DataSource = items;
repeater.DataBind();

Таким образом, вся фильтрация применяется заранее

Это также сократит количество обращений к базе данных, что повышает производительность

2 голосов
/ 11 марта 2012

Ответ очень прост: вы просто установите для свойства Visible значение false для элемента, и он не будет отображаться. В этом примере я удаляю элементы из списка продуктов, которые доступны новым клиентам, только если текущий пользователь имеет историю покупок:

void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (!userHasPurchaseHistory) { return; }
            // filter out products only allowed for new members
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                System.Data.Common.DbDataRecord rec = (System.Data.Common.DbDataRecord)e.Item.DataItem;
                if (rec != null)
                {
                    bool newMemberOnly = Convert.ToBoolean(rec["NewMemberOnly"]);
                    if (newMemberOnly) { e.Item.Visible = false; }
                }
            }

        }

Обратите внимание, что вышеприведенное относится к IDataReader, вам может потребоваться привести e.Item.DataItem к другому объекту в зависимости от того, к чему вы привязываетесь.

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

2 голосов
/ 08 февраля 2010

Я согласен с остальными ответами - лучшее решение (как для производительности, так и для ясности кода) - изменить дизайн страницы, чтобы можно было отфильтровать недействительные записи перед привязкой данных.

Большинство источников данных не позволяют нам удалять их элементы, пока ASP.NET их итерирует. Например, если вы связываетесь с простым универсальным List<T> и удаляете элемент во время его итерации, список выдаст InvalidOperationException.

В других случаях ASP.NET фактически выполняет итерацию копии источника данных. Если вы связываетесь с DataTable, ASP.NET использует копию содержимого (DataView по умолчанию), а не выполняет итерацию самих исходных строк - вы можете удалять элементы из базового источника данных во время итерации, но это не влияет операция привязки данных.

Если предварительная фильтрация элементов на самом деле не подходит, ваше текущее решение подойдет: просто спрячьте элементы! Если вам нужно получить правильное число, отследите количество недопустимых элементов в вашем обработчике ItemDataBound и представьте его как свойство уровня страницы:

if (IsInvalid(args.Item.DataItem)) {
    this.invalidItemCount++;
    // code to hide the current item
}
2 голосов
/ 08 февраля 2010

Почему бы не отфильтровать источник данных перед привязкой. Итак, если вы используете несколько пользовательских объектов:

myRepeater.DataSource=repository.getItems().Where(item=>item.Language==CurrentLanguage);

Если они вам не нужны, не связывайте их в первую очередь.

Обновление

Если это вообще возможно, вам следует извлечь эту информацию из базы данных заранее. Эти списки большие? Если это так, то удар по БД один раз для каждого элемента в списке будет отображаться как проблема с производительностью.

...