Практическое руководство. Добавление и удаление элементов с помощью элемента управления ListView в Windows Forms
Процесс добавления элемента в элемент управления ListView Windows Forms состоит в основном из указания элемента и назначения ему свойств. Добавление или удаление элементов списка можно выполнять в любое время.
Добавление элементов программным способом
- Используйте метод Add свойства Items.
// Adds a new item with ImageIndex 3 listView1.Items.Add("List item text", 3);
' Adds a new item with ImageIndex 3 ListView1.Items.Add("List item text", 3)
Удаление элементов программным способом
- Используйте метод RemoveAt или Clearсвойства Items. Метод RemoveAt удаляет один элемент, а метод Clear удаляет все элементы из списка.
// Removes the first item in the list. listView1.Items.RemoveAt(0); // Clears all the items. listView1.Items.Clear();
' Removes the first item in the list. ListView1.Items.RemoveAt(0) ' Clears all items: ListView1.Items.Clear()
См. также
- ListView
- Элемент управления ListView
- Общие сведения об элементе управления ListView
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Элемент управления ListView

— это исключительно гибкий привязанный к данным элемент управления, отображающий свое содержимое на основе определяемых вами шаблонов. В отличие от Repeater, элемент ListView добавляет высокоуровневые средства, такие как возможность выбора и редактирования, которые работают точно так же, как аналогичные средства GridView. Но в отличие от GridView, элемент ListView не поддерживает модели, основанной на полях, для создания быстрых и простых таблиц с минимальным кодом разметки.
С разных точек зрения ListView можно трактовать либо как более гибкую версию GridView, требующую больше работы, либо как более насыщенную средствами версию простого элемента Repeater, который появился в ASP.NET 1.x.
ListView включает более широкий набор шаблонов, чем GridView. Эти шаблоны перечислены в таблице ниже:
Устанавливает содержимое каждого элемента данных (если вы не используете AlternatingItemTemplate) или каждой нечетной ячейки (если используете)
Применяется в сочетании с ItemTemplate для различного форматирования четных и нечетных строк
Устанавливает содержимое разделителя, размещаемого между элементами
Устанавливает содержимое элемента, выбранного в данный момент. Можно использовать то же содержимое, что и ItemSeparatorTemplate, но с другим форматированием, или же выбрать отображение расширенного вида с дополнительными деталями для выбранного элемента
Устанавливает элементы управления, используемые для элемента в режиме редактирования
Устанавливает элементы управления, используемые для вставки нового элемента
Устанавливает разметку, обертывающую ваш список элементов
Устанавливает разметку, обертывающую каждую группу элементов, если используется средство группирования
Устанавливает содержимое разделителя групп элементов
Устанавливает содержимое, используемое для заполнения пустых значений в последней группе, если применяется группирование. Например, если создаются группы из 5 элементов, а источником данных является коллекция из 13 объектов, то в последней группе будет не хватать 2 элементов
Устанавливает разметку, используемую в случае пустого привязанного объекта данных (т.е. не содержащего записей или объектов)
Наиболее частая причина использования ListView связана с необходимостью создания необычной компоновки, например, чтобы построить таблицу, размещающую более одного элемента в одной строке, или же вообще не использующую обычную табличную компоновку. При построении страницы, предназначенной для отображения больших объемов данных, разработчики на ASP.NET обычно сначала обращаются к GridView, a ListView применяют в более специализированных сценариях.
При отображении некоторых данных в ListView вы следуете тому же процессу, что и в случае элемента GridView, состоящего из столбцов TemplateField. Сначала вы создаете разметку для шаблонов, которые хотите использовать. Как минимум, понадобится шаблон ItemTemplate, который представляет содержимое для каждого элемента. Ниже приведен пример:
-
, ,
При визуализации элемент управления ListView осуществляет проход по привязанным данным и отображает ItemTemplate для каждого элемента. Все это содержимое размещается внутри обычного элемента :

Часто возникает желание определить шаблон LayoutTemplate для получения большего контроля над расположением элементов. В этом случае список элементов размещается внутри LayoutTemplate. Поведение по умолчанию элемента ListView без LayoutTemplate эквивалентно использованию примерно следующего шаблона LayoutTemplate:
При создании LayoutTemplate для ListView потребуется указать, куда должно быть вставлено содержимое ItemTemplate. Это делается добавлением заполнителя — элемент, который будет дублироваться по одному для каждого элемента привязанных данных. Чтобы обозначить элемент как заполнитель, необходимо просто установить его ID в itemPlaceHolder, как показано выше в примере.
Заполнитель должен быть серверным элементом управления — другими словами, ему нужен атрибут runat=»server». В этом примере используется удобный веб-элемент управления PlaceHolder, но вместо него можно указать серверный элемент или .
По сравнению с GridView, элемент Listview обладает одним концептуальным недостатком — у него есть только один шаблон для отображения элементов. Чтобы понять, чем это может ограничивать, рассмотрим, что случится, если вы захотите создать многостолбцовое отображение с использованием Listview. Вам нужно будет добавить заголовки столбцов над Listview, а затем определить содержимое всех столбцов в ItemTemplate. Это отлично работает, но приводит к серьезным неудобствам, когда требуется внести кажущиеся тривиальными изменения — вроде изменения последовательности столбцов.
-
, ,
Результат быстро станет трудночитаемым, если отображаемый набор данных окажется достаточно объемным (если не применять разбиение на страницы):

Группирование
Элемент Listview предоставляет возможность создать несколько более структурированные отображения, которые решают проблему, показанную на рисунке выше. Трюк заключается в применении группирования, которое позволяет указать дополнительный уровень компоновки, используемой для размещения небольших групп записей внутри общей компоновки.
Чтобы воспользоваться группированием, начать следует с установки свойства GroupItemCount, определяющего количество элементов данных в каждой группе:
К сожалению, средство группирования ListView не работает в связке с информацией из привязанных данных. Например, в случае привязки коллекции объектов Product не существует способа разделить их по группам на основе ценовых диапазонов или категорий товаров. Вместо этого группы ListView всегда имеют фиксированный размер. Максимум, что можно — это сделать размер групп настраиваемым пользователем (скажем, применив дополнительный элемент управления, подобный раскрывающемуся списку, из которого пользователь сможет выбирать число для применения в GroupItemCount).
После установки размера группы понадобится изменить LayoutTemplate. Это связано с тем, что общая компоновка более не содержит элементов данных. Вместо этого она содержит группы, которые, в свою очередь, содержат элементы. Чтобы отразить этот факт, вы должны изменить ID с itemPlaceholder на groupPlaceholder. В данном примере каждая группа представляет собой отдельную строку:
Далее необходимо применить шаблон GroupTemplate, который используется в качестве оболочки для каждой группы. GroupTemplate должен предоставлять заполнитель элемента, который находился ранее в LayoutTemplate. В этом примере каждый элемент является отдельной ячейкой:

При использовании группирования последняя группа может быть заполнена не полностью. Например, в предыдущем примере создается группа из трех элементов. Если количество элементов данных не кратно трем, последняя группа будет неполной. Во многих случаях это не представляет проблемы, но в некоторых возникает сложность — например, если нужно сохранить некоторую структуру или поместить какое-то альтернативное содержимое в таблицу. В такой ситуации можно предоставить новое содержимое, используя EmptyItemTemplate.
Разбиение на страницы
В отличие от других элементов управления, рассматриваемых ранее, ListView не имеет жестко связанного средства разбиения на страницы. Взамен ListView поддерживает другой элемент управления, предназначенный для разбиения на страницы, а именно: DataPager.
Идея, положенная в основу DataPager, заключается в том, что он предлагает простой, согласованный способ использования разбиения на страницы для широкого разнообразия элементов управления. В настоящее время ListView — единственный элемент, поддерживающий DataPager. Однако вполне резонно ожидать, что в будущих версиях DataPager будет работать с другими элементами управления ASP.NET.
Одно из преимуществ DataPager заключается в том, что вам предоставляется гибкость в произвольном размещении его внутри общей компоновки — просто за счет размещения дескриптора в правильном месте LayoutTemplate. Рассмотрим пример совершенно типичного размещения DataPager в нижней части ListView, с кнопками для перемещения вперед и назад на одну страницу либо для быстрого перехода на первую или последнюю страницы:
DataPager также усекает привязанные данные, так что ListView получает соответствующее подмножество этих данных. В текущем примере страницы ограничены тремя элементами. На рисунке показаны кнопки перемещения по страницам:
ListView
В ранних версиях Android компонент ListView был одним из самым популярных элементов интерфейса. Но теперь его время ушло, недаром на панели инструментов студии он находится в разделе Legacy (устаревший код).
ListView представляет собой прокручиваемый список элементов. Очень популярен на мобильных устройства из-за своего удобства. Даже кот способен пользоваться этим элементом, проводя лапкой по экрану вашего телефона.

Компонент ListView более сложен в применении по сравнению с TextView и другим простыми элементами. Работа со списком состоит из двух частей. Сначала мы добавляем на форму сам ListView, а затем заполняем его элементами списка.
Рассмотрим для начала самый простой пример. Поместите на форму компонент ListView и присвойте идентификатор. Вы увидите, что список будет содержать несколько элементов Item и Sub Item.

Однако, если посмотрим XML-код, то там ничего не увидим.
Переходим в класс активности и пишем следующий код:
// код пишется в методе onCreate() // получаем экземпляр элемента ListView ListView listView = findViewById(R.id.listView); // определяем строковый массив final String[] catNames = new String[] < "Рыжик", "Барсик", "Мурзик", "Мурка", "Васька", "Томасина", "Кристина", "Пушок", "Дымка", "Кузя", "Китти", "Масяня", "Симба" >; // используем адаптер данных ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, catNames); listView.setAdapter(adapter);
Вот и всё. Давайте разберёмся с кодом.
Адаптеры — заполнение списка данными
Компоненту ListView требуются данные для наполнения. Источником наполнения могут быть массивы, базы данных. Чтобы связать данные со списком, используется так называемый адаптер.
Адаптер для стандартного списка обычно создаётся при помощи конструкции new ArrayAdapter(Context context, int textViewResourceId, String[] objects).
- context — текущий контекст
- textViewResourceId — идентификатор ресурса с разметкой для каждой строки. Можно использовать системную разметку с идентификатором android.R.layout.simple_list_item_1 или создать собственную разметку
- objects — массив строк
Метод setAdapter(ListAdapter) связывает подготовленный список с адаптером.
Переходим к java-коду. Сначала мы получаем экземпляр элемента ListView в методе onCreate(). Далее мы определяем массив типа String. И, наконец, используем адаптер данных, чтобы сопоставить данные с шаблоном разметки. Выбор адаптера зависит от типа используемых данных. В нашем случае мы использовали класс ArrayAdapter.
Отступление
Если вы будете брать строки из ресурсов, то код будет таким:
final String[] catNames = < getResources().getString(R.string.name1), getResources().getString(R.string.name2), getResources().getString(R.string.name3), getResources().getString(R.string.name4), getResources().getString(R.string.name5), >;
А будет еще лучше, если вы воспользуетесь специально предназначенным для этого случая типом ресурса . В файле res/values/strings.xml добавьте следующее:
- Рыжик
- Барсик
- Мурзик
- Мурка
- Васька
- Томасина
- Кристина
- Пушок
- Дымка
- Кузя
- Китти
- Масяня
- Симба
И тогда в коде используйте для объявления массива строк:
String[] catNames = getResources().getStringArray(R.array.cat_names);
Запустив проект, вы увидите работающий пример прокручиваемого списка. Правда, созданный список пока не реагирует на нажатия. Но при нажатии выбранный элемент выделяется цветным прямоугольником (в версии Android 2.3 был оранжевый, а в Android 4.0 — синий, потом был серый цвет и т.д.).

Собственная разметка
В примере мы используем готовую системную разметку android.R.layout.simple_list_item_1, в которой настроены цвета, фон, высота пунктов и другие параметры. Но нет никаких препятствий самому создать собственную разметку под своё приложение.
Но для начала неплохо бы взглянуть на содержание системной разметки. Студия позволяет увидеть исходный код, достаточно в коде поставить курсор на simple_list_item_1 и нажать на комбинацию клавиш Ctrl+B. Наш simple_list_item_1 выглядит так (в одной из версий):
Мы видим, что в качестве разметки используется TextView с набором атрибутов.
Если говорить о системных разметках, то имеется несколько вариантов. Вкратце ознакомимся с ними.
android.R.layout.simple_list_item_1
Состоит из одного TextView (см. выше)
| android.resource.id.text1 |
android.R.layout.simple_list_item_2
Состоит из двух TextView — один побольше сверху и второй поменьше под ним.
| android.resource.id.text1 |
| android.resource.id.text2 |
android.R.layout.simple_list_item_checked
Справа от CheckedTextView будет находиться флажок
| android.resource.id.text1 |
android.R.layout.activity_list_item
Слева от TextView находится значок ImageView с идентификатором android.resource.id.Icon.
| android.resource.id.text1 |
Создадим свой шаблон для отдельного пункта списка. Для этого в папке res/layout/ создадим новый файл list_item.xml:
В некоторых случаях желательно установить атрибут android:background=»?android:attr/activatedBackgroundIndicator» у родительского элемента, чтобы элементы списка реагировали на нажатие изменением цвета. Можно задать и собственное поведение.
Вы можете настраивать все атрибуты у TextView, кроме свойства Text, так как текст будет автоматически заполняться элементом ListView программным путём. Ну, а дальше просто меняете в коде системную разметку на свою:
ArrayAdapter adapter = new ArrayAdapter(this, R.layout.list_item, catNames);
При создании собственного элемента списка, состоящего из TextView можете использовать специальный стиль для минимального размера текста.
Динамическое заполнение списка
Рассмотрим пример динамического заполнения списка, когда список изначально пуст и пользователь сам добавляет новые элементы. Разместим на экране текстовое поле, в котором пользователь будет вводить известные ему имена котов. Когда пользователь будет нажимать на клавишу Enter на клавиатуре, то введённое имя кота будет попадать в список.
@Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // получаем экземпляр элемента ListView ListView listView = (ListView) findViewById(R.id.listView); final EditText editText = (EditText) findViewById(R.id.editText); // Создаём пустой массив для хранения имен котов final ArrayListcatNames = new ArrayList<>(); // Создаём адаптер ArrayAdapter, чтобы привязать массив к ListView final ArrayAdapter adapter; adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, catNames); // Привяжем массив через адаптер к ListView listView.setAdapter(adapter); // Прослушиваем нажатия клавиш editText.setOnKeyListener(new View.OnKeyListener() < public boolean onKey(View v, int keyCode, KeyEvent event) < if (event.getAction() == KeyEvent.ACTION_DOWN) if (keyCode == KeyEvent.KEYCODE_ENTER) < catNames.add(0, editText.getText().toString()); adapter.notifyDataSetChanged(); editText.setText(""); return true; >return false; > >); >
При нажатии на Enter мы получаем текст из текстового поля и заносим его в массив. А также оповещаем адаптер об изменении, чтобы список автоматически обновил своё содержание.

У нас получился каркас для чата, когда пользователь вводит текст и он попадает в список. Далее надо получить текст от другого пользователя и также добавить в список. К слову сказать, слово chat с французского означает «кошка». Но это уже совсем другая история.
Прослушивание событий элемента ListView
Нам нужно реагировать на определенные события, генерируемые элементом ListView, в частности, нас интересует событие, которое возникает, когда пользователь нажимает на один из пунктов списка.
В этом нам поможет метод setOnItemClickListener элемента ListView и метод OnItemClick() интерфейса AdapterView.OnItemClickListener.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View itemClicked, int position, long id) < Toast.makeText(getApplicationContext(), ((TextView) itemClicked).getText(), Toast.LENGTH_SHORT).show(); >>);
Теперь при нажатии на любой элемент списка мы получим всплывающее сообщение, содержащее текст выбранного пункта.
Естественно, мы можем не только выводить сообщения, но и запускать новые активности и т.п.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View itemClicked, int position, long id) < TextView textView = (TextView) itemClicked; String strText = textView.getText().toString(); // получаем текст нажатого элемента if(strText.equalsIgnoreCase(getResources().getString(R.string.name1))) < // Запускаем активность, связанную с определенным именем кота startActivity(new Intent(this, BarsikActivity.class)); >> >);
В метод onItemClick() передаётся вся необходимая информация, необходимая для определения нажатого пункта в списке. В приведенном выше примере использовался простой способ — приводим выбранный элемент к объекту TextView, так как известно, что в нашем случае все пункты являются элементами TextView (Для дополнительной проверки можете использовать оператор instanceOf). Мы извлекаем текст из выбранного пункта и сравниваем его со своей строкой.
Также можно проверять атрибут id для определения нажатия пункта списка.
Программное нажатие на элемент списка
Вдруг вам захочется программно нажать на элемент списка. Мы задали код, который будет выполняться при нажатии, в предыдущем примере. Теперь добавим кнопку и напишем код для щелчка.
public void onClick(View view) < int activePosition = 0; // первый элемент списка listView.performItemClick(listView.getAdapter(). getView(activePosition, null, null), activePosition, listView.getAdapter(). getItemId(activePosition)); >
Код громоздкий, но работоспособный.
ListView не реагирует на нажатия
В некоторых случаях нажатия на пунктах меню не срабатывают. Ниже приводятся несколько возможных причин.
Элемент списка содержит CheckBox, который также имеет свой слушатель нажатий. Попробуйте удалить фокус у него:
android:focusable="false" android:focusableInTouchMode="false"
Попробуйте переместить OnItemClickListener перед установкой адаптера. Иногда помогает.
Элемент списка содержит ImageButton. Установите фокус в false:
ImageButton imageButton = (ImageButton) convertView.findViewById(R.id.imageButton); imageButton.setFocusable(false);
Элемент списка содержит TextView. Если вы используете атрибут android:inputType=»textMultiLine», то замените его на android:minLines/android:maxLines.
Элемент списка содержит TextView, содержащий ссылку на веб-страницу или электронный адрес. Удалите атрибут android:autoLink.
Настраиваем внешний вид ListView
У ListView есть несколько полезных атрибутов, позволяющих сделать список более привлекательным. Например, у него есть атрибут divider, который отвечает за внешний вид разделителя, а также атрибут dividerHeight, отвечающий за высоту разделителя. Мы можем установить какой-нибудь цвет или даже картинку для разделителя. Например, создадим для разделителя цветовой ресурс с красным цветом, а также ресурс размера для его высоты:
#FF0000 2dp
Далее присвоим созданный ресурс атрибуту divider, а также зададим его высоту в атрибуте dividerHeight у нашего элемента ListView:

Если вас не устраивает стандартный разделитель, что можете нарисовать какую-нибудь волнистую черту, сохранить ее в PNG-файле и использовать как drawable-ресурс. Проделайте это самостоятельно.
Можно работать с данными атрибутами программно:
ColorDrawable divcolor = new ColorDrawable(Color.DKGRAY); listView.setDivider(divcolor); listView.setDividerHeight(2);
Если хотите убрать разделители, то используйте прозрачный цвет.
listView.setDivider(getResources().getDrawable(android.R.color.transparent));
Заметил, что порядок вызова двух методов важен, если установку высоты вызвать перед установкой цвета разделителя, то метод затирает цвет и результат будет такой же, как с прозрачным цветом.
Обратите внимание, что по умолчанию разделитель не выводится перед первым и последним элементом списка. Если вы хотите изменить эти настройки, то используйте свойства Footer dividers enabled (атрибут footerDividersEnabled) и Header dividers enabled (атрибут headerDividersEnabled):
. android:footerDividersEnabled="true" android:headerDividersEnabled="true" .
Пользовательский селектор
Мы уже видели, что по умолчанию выбранный элемент списка выделяется при помощи цветной полоски. Данный селектор также можно настроить через атрибут android:listSelector. Создайте какую-нибудь текстуру для селектора и привяжите его через ресурс. Вот образец текстурированного ореола желтого цвета для селектора.

Нужно подготовить сначала файл res/drawable/selector.xml:
Если вам нужно сразу подсветить нужный элемент списка при запуске программы, то используйте связку двух методов:
listView.requestFocusFromTouch(); listView.setSelection(4); // выбираем 5 пункт списка
Множественный выбор
ListView позволяет выбирать не только один пункт, но и несколько. В этом случае нужно установить свойство Choice Mode в значение multiplyChoice, что соответствует атрибуту android:choiceMode=»multipleChoice».
Также множественный выбор можно установить программно при помощи метода setChoiceMode(ListView.CHOICE_MODE_MULTIPLE).
Теперь, если создать массив строк, например список продуктов для кошачьего завтрака, то получим следующий результат.
public class MultiChoiceListViewActivity extends Activity < ListView choiceList; TextView selection; String[] foods = < "Молоко", "Сметана", "Колбаска", "Сыр", "Мышка", "Ананас", "Икра черная", "Икра кабачковая", "Яйцо" >; @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); selection = (TextView) findViewById(R.id.textView1); choiceList = (ListView) findViewById(R.id.listView1); ArrayAdapteradapter = new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice, foods); // choiceList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); choiceList.setAdapter(adapter); > >

Осталось только программно получить отмеченные пользователем элементы списка. Вот мой список продуктов, который я хочу предложить коту. Надеюсь, ему понравится мой выбор. Выбранные элементы будем помещать в TextView:
choiceList.setOnItemClickListener(new OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View v, int position, long id) < // Очистим TextView selection.setText(""); // получим булев массив для каждой позиции списка // Объект SparseBooleanArray содержит массив значений, к которым можно получить доступ // через valueAt(index) и keyAt(index) SparseBooleanArray chosen = ((ListView) parent).getCheckedItemPositions(); for (int i = 0; i < chosen.size(); i++) < // если пользователь выбрал пункт списка, // то выводим его в TextView. if (chosen.valueAt(i)) < selection.append(foods[chosen.keyAt(i)] + " "); >> > >);

Если нужно получить отдельно список выбранных и невыбранных элементов списка, то можно написать следующее:
choiceList.setOnItemClickListener(new OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View v, int position, long id) < // Очистим TextView перед вставкой нового контента. selection.setText(""); int cntChoice = choiceList.getCount(); String checked = ""; String unchecked = ""; SparseBooleanArray sparseBooleanArray = choiceList .getCheckedItemPositions(); for (int i = 0; i < cntChoice; i++) < if (sparseBooleanArray.get(i) == true) < checked += choiceList.getItemAtPosition(i).toString() + "\n"; // выводим список выбранных элементов //selection.setText(checked); >else if (sparseBooleanArray.get(i) == false) < unchecked += choiceList.getItemAtPosition(i).toString() + "\n"; // выводим список невыбранных элементов selection.setText(unchecked); >> > >);
Переменная checked будет содержать список выбранных элементов, а переменная unchecked — список невыбранных элементов.
Следует отметить, что в примерах использовался старый метод getCheckedItemPositions(), доступный с Android 1. В Android 2.2 появился новый метод getCheckedItemIds(). Учтите, что с новым методом можно получить массив только выбранных элементов, хотя в большинстве случаев этого достаточно. Но данный метод требует своих заморочек и в данном моём примере он не заработал.
Подсветка нажатий
На данный момент используется следующая техника подсвечивания элементов списка при нажатии. Здесь учитывается версия Android (до и после API 21).
res/values/colors.xml
#cccccc #ff64c2f4
res/drawable/item_selector.xml
res/drawable-v21/item_selector.xml
Разница заключается в том, что в версии 21 рекомендуется использовать серый цвет с применением ripple.
Созданные ресурсы следует применить для фона элемента списка (list_item.xml): android:background=»@drawable/item_selector».
Для проверки установим режим singleChoice для активации выбранного элемента списка.
Обычно режим активации выбранного элемента списка применяют для двухпанельной разметки, а в телефонах такой режим не используют. В таких случаях удобнее создать специальный стиль для списка.
Создадим стиль для планшетов.
res/values-sw600dp/styles.xml
А в обычном styles.xml оставим заглушку.
Теперь применим стиль к списку и нужное поведение с активацией будет применяться только на планшетах.
При повороте выбранный пункт списка может оказаться за пределами экрана. С помощью метода smoothScrollToPosition() мы можем автоматически прокрутить список к нужному месту. Код показан в продвинутых приёмах.
Кнопка под списком
Если вы хотите разместить кнопку под списком, которая бы не зависела от количества элементов в ListView, то воспользуйтесь весом (layout_weight).
Плавная прокрутка в начало списка или любую позицию
У списка есть специальный метод smoothScrollToPosition(), позволяющий плавно прокрутить до нужного места. Достаточно в методе указать номер позиции для прокрутки:
ListView listView = (ListView) findViewById(R.id.listView); int n = 0; // прокручиваем до начала listView.smoothScrollToPosition(n);
Учтите, что если элементов в списке несколько сотен и вы запустите плавную прокрутку указанным способом, то процесс может растянуться надолго. Например, коты могут и заснуть, не дождавшись конца операции. Задумайтесь.
Настраиваем прокрутку
У ListView есть атрибуты для настройки внешнего вида полосы прокрутки
android:scrollbarTrackVertical="@drawable/scrool_bg" android:scrollbarThumbVertical="@drawable/scroll"
Аналогично это применимо к полосам прокрутки у ScrollView, EditText и т.д.
ListActivity
Если вам нужна форма, состоящая только из списка, то вам проще воспользоваться системным классом ListActivity вместо стандартного Activity. Именно такой подход описан в документации по ListView. Пример работы описан в статье ListActivity — создаём прокручиваемый список.
Настройка цвета при достижении края прокрутки
Когда прокрутка достигает конца (сверху или снизу), то выводится цветовой эффект. В API 21 появилась возможность управлять этим эффектом через атрибут colorEdgeEffect:
Далее применяем как тему.
Для более старых устройств такую настройку сделать нельзя.
Нет данных для отображения
Если адаптер не содержит данных для отображения, то можете вызвать метод для показа пустой разметки:
listView.setEmptyView(view);
Добавляем шапку и подвал
В подвалах часто живут коты, поэтому списки желательно также снабжать подвалом (и шапкой). У ListView есть такая возможность, давайте воспользуемся этим.
Элементами шапки и подвала могут послужить View, которые могут быть добавлены к списку сверху и снизу через методы addHeaderView() и addFooterView(). В принципе оба элемента одинаковы, только добавляются в разные места списка.
Полный варианты методов:
addHeaderView (View v, Object data, boolean isSelectable) addFooterView (View v, Object data, boolean isSelectable)
- v – компонент, который отобразится, как пункт списка
- data – объект, связанный с этим пунктом списка
- isSelectable – можно ли будет кликать на пункт или выделять его
Интересно, что до версии API 19 шапку и подвал можно было добавлять только до присвоения списку адаптера, иначе возникала ошибка. Теперь можно добавлять в любое время, ошибки не будет и список будет работать.
Для демонстрации подойдёт любой урок со списком. Дополнительно добавим два файла для шапки и подвала (можно также воспользоваться системной разметкой). Если по структуре шапка и подвал одинаковы, то можно обойтись и одним файлом. Но для разнообразия сделаем их немного разными.
res/layout/list_header.xml
res/layout/list_footer.xml
Осталось подключить шапку и подвал к списку. Напоминаю, что можете использовать любой пример со списком. Поэтому часть кода опущу.
View header; View footer; // Их может быть несколько // View header2; // View footer2; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.listView); // создаем шапку и подвал header = createHeader("Текст для шапки"); footer = createFooter("Подвал"); // можете добавлять несколько шапок и подвалов //header2 = createHeader("Шапка 2"); //footer2 = createFooter("Подвал 2"); listView.addHeaderView(header); listView.addFooterView(footer); //listView.addHeaderView(header2, "Текст для другой шапки", false); //listView.addFooterView(footer2, "Текст для другого подвала", false); // Какой-то адаптер mAdapter = new ZodiacAdapter(this); listView.setAdapter(mAdapter); >// создание шапки View createHeader(String text) < View view = getLayoutInflater().inflate(R.layout.list_header, null); ((TextView)view.findViewById(R.id.textViewHeaderText)).setText(text); return view; >// создание подвала View createFooter(String text)
Никто не запрещает использовать несколько шапок и подвалов в списке. Соответствующий код закомментирован.
Шапка состоит из двух текстовых меток. В первой метке текст задан в макете, а во второй текст устанавливается программно. Подвал сделан ещё проще — только одна метка, текст задан в макете. Естественно, вы можете реализовать более сложный макет в вашем приложении.
Шапку и подвал можно удалить программно через методы removeHeaderView() и removeFooterView().
Вывод из базы данных в ListView WPF
Есть база данных с таблицей, которая имеет поля: Имя, Фамилия, место работы и фото (туда помещается путь к файлу). Необходимо вывести список всех людей из базы данных с фотками в ListView. Хотел попробовать сделать как вывод в DataGrid’е или через EntitiesFramework проходиться по каждому столбцу и биндить их в XAML, но сбился с мысли и теперь все в каше. Буду очень рад любым подсказкам, как можно было бы это реализовать!
Отслеживать
задан 23 мар 2021 в 20:20
33 1 1 серебряный знак 6 6 бронзовых знаков
у ListView можно задать дочерний GridView, который умеет рисовать таблички
23 мар 2021 в 21:23
@aepot То есть, просто прибиндить к GridViewColumns столбцы из бд? А как он будет вести себя с графическими объектами, к которым указывается путь?
23 мар 2021 в 21:33
Я не пробовал, биндил только к обычной коллекции.
23 мар 2021 в 21:42
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вот простой пример отображения таблицы из БД в ListView, без разделения на слои и использования EF.
Пусть у нас есть база данных base в SQL Server, и в ней таблица Users:
CREATE TABLE [dbo].[Users]( [Name] [nvarchar](200) NULL, [Surname] [nvarchar](200) NULL, [Image] [nvarchar](max) NULL )
Тогда мы можем написать такой код для загрузки данных:
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; using System.Windows; using System.Windows.Controls; namespace WpfTest < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >static DataTable ExecuteSql(string sql) < DataTable dt=new DataTable(); SqlConnection conn = new SqlConnection( "Data Source=.\\SQLEXPRESS;Integrated Security=True;Initial Catalog=base" ); using (conn) < conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); SqlDataReader read = cmd.ExecuteReader(); using (read) < dt.Load(read); >> return dt; > private void Button_Click(object sender, RoutedEventArgs e) < DataTable dt = ExecuteSql("SELECT * FROM Users"); listviewUsers.ItemsSource = dt.DefaultView; >> >
"/>

Здесь мы создаем две колонки с обычной привязкой к строковому свойству, и одну — с нестандартным шаблоном, который отображает Image. При использовании EF все будет аналогично, только привязывать ItemsSource вы будете к коллекции конкретных сущностей вместо DataTable.
Если в базе хранится не полный путь, а имя файла относительно общего каталога, нужно ввести дополнительный класс и преобразовывать путь при чтении из базы:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using System.Windows; using System.Windows.Controls; namespace WpfTest < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >static IEnumerable ExecuteSql(string sql) < const string dir = "C:\\Test\\Images\\"; SqlConnection conn = new SqlConnection( "Data Source=.\\SQLEXPRESS;Integrated Security=True;Initial Catalog=base" ); using (conn) < conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); SqlDataReader read = cmd.ExecuteReader(); using (read) < while (true) < if (read.Read() == false) break; User user = new User() < Name = (string)read["Name"], Surname = (string)read["Surname"], Image = Path.Combine( dir , (string)read["Image"]) >; yield return user; > > > > private void Button_Click(object sender, RoutedEventArgs e) < User[] users = ExecuteSql("SELECT * FROM Users").ToArray(); listviewUsers.ItemsSource = users; >> public class User < public string Name < get; set; >public string Surname < get; set; >public string Image < get; set; >> >