Добавление кнопки в список в WinForms

Есть ли способ добавить кнопку управления в ячейку внутри ListView в приложении WinForms?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
28
0
90 301
11

Ответы 11

Может это может быть интересно?

http://www.codeproject.com/KB/list/extendedlistviews.aspx

Сам ListView (или ListViewItem) не функционирует как контейнер любого типа, поэтому нет возможности напрямую добавлять элементы управления, однако это выполнимо. Я успешно использовал этот расширенный ListView: Встраивание элементов управления в ListView.

Нет, стандартный ListView Windows Forms не поддерживает встроенные элементы управления. Вы можете попробовать создать свой собственный элемент управления или использовать что-то вроде http://www.codeproject.com/KB/list/EXListView.aspx.

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

Раньше я случайно сталкивался с обсуждением, надеюсь, это поможет: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/ee232cc4-68c5-4ed3-9ea7-d4d999956504/

Возможно, стоит упомянуть, что элемент управления представлением списка может быть разработан в WPF как пользовательский / настраиваемый элемент управления с кнопками в его ListViewItems, а затем использовать этот элемент управления в приложении WinForms в элементе управления ElementHost.

Вот код класса ListViewExtender, который можно использовать повторно. Это не производный класс ListView, в основном вы просто объявляете, что определенный столбец отображается в виде кнопок, а не текста. Текст кнопки - это текст подэлемента.

Он позволяет без проблем просматривать списки большого размера, не использует p / invoke, а также работает с горизонтальными полосами прокрутки (некоторый код, предложенный в качестве ответов здесь, не работает или довольно медленный с большим количеством элементов). Обратите внимание, что для расширенного ListView требуется, чтобы для FullRowSelect было установлено значение true, а для типа представления было установлено значение Details.

Это пример кода, который его использует:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent(); // you need to add a listView named listView1 with the designer
            listView1.FullRowSelect = true;
            ListViewExtender extender = new ListViewExtender(listView1);
            // extend 2nd column
            ListViewButtonColumn buttonAction = new ListViewButtonColumn(1);
            buttonAction.Click += OnButtonActionClick;
            buttonAction.FixedWidth = true;

            extender.AddColumn(buttonAction);

            for (int i = 0; i < 10000; i++)
            {
                ListViewItem item = listView1.Items.Add("item" + i);
                item.SubItems.Add("button " + i);
            }
        }

        private void OnButtonActionClick(object sender, ListViewColumnMouseEventArgs e)
        {
            MessageBox.Show(this, @"you clicked " + e.SubItem.Text);
        }
    }
}

Вот код ListViewExtender и связанные классы:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace WindowsFormsApplication1
{
    public class ListViewExtender : IDisposable
    {
        private readonly Dictionary<int, ListViewColumn> _columns = new Dictionary<int, ListViewColumn>();

        public ListViewExtender(ListView listView)
        {
            if (listView == null)
                throw new ArgumentNullException("listView");

            if (listView.View != View.Details)
                throw new ArgumentException(null, "listView");

            ListView = listView;
            ListView.OwnerDraw = true;
            ListView.DrawItem += OnDrawItem;
            ListView.DrawSubItem += OnDrawSubItem;
            ListView.DrawColumnHeader += OnDrawColumnHeader;
            ListView.MouseMove += OnMouseMove;
            ListView.MouseClick += OnMouseClick;

            Font = new Font(ListView.Font.FontFamily, ListView.Font.Size - 2);
        }

        public virtual Font Font { get; private set; }
        public ListView ListView { get; private set; }

        protected virtual void OnMouseClick(object sender, MouseEventArgs e)
        {
            ListViewItem item;
            ListViewItem.ListViewSubItem sub;
            ListViewColumn column = GetColumnAt(e.X, e.Y, out item, out sub);
            if (column != null)
            {
                column.MouseClick(e, item, sub);
            }
        }

        public ListViewColumn GetColumnAt(int x, int y, out ListViewItem item, out ListViewItem.ListViewSubItem subItem)
        {
            subItem = null;
            item = ListView.GetItemAt(x, y);
            if (item == null)
                return null;

            subItem = item.GetSubItemAt(x, y);
            if (subItem == null)
                return null;

            for (int i = 0; i < item.SubItems.Count; i++)
            {
                if (item.SubItems[i] == subItem)
                    return GetColumn(i);
            }
            return null;
        }

        protected virtual void OnMouseMove(object sender, MouseEventArgs e)
        {
            ListViewItem item;
            ListViewItem.ListViewSubItem sub;
            ListViewColumn column = GetColumnAt(e.X, e.Y, out item, out sub);
            if (column != null)
            {
                column.Invalidate(item, sub);
                return;
            }
            if (item != null)
            {
                ListView.Invalidate(item.Bounds);
            }
        }

        protected virtual void OnDrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.DrawDefault = true;
        }

        protected virtual void OnDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            ListViewColumn column = GetColumn(e.ColumnIndex);
            if (column == null)
            {
                e.DrawDefault = true;
                return;
            }

            column.Draw(e);
        }

        protected virtual void OnDrawItem(object sender, DrawListViewItemEventArgs e)
        {
            // do nothing
        }

        public void AddColumn(ListViewColumn column)
        {
            if (column == null)
                throw new ArgumentNullException("column");

            column.Extender = this;
            _columns[column.ColumnIndex] = column;
        }

        public ListViewColumn GetColumn(int index)
        {
            ListViewColumn column;
            return _columns.TryGetValue(index, out column) ? column : null;
        }

        public IEnumerable<ListViewColumn> Columns
        {
            get
            {
                return _columns.Values;
            }
        }

        public virtual void Dispose()
        {
            if (Font != null)
            {
                Font.Dispose();
                Font = null;
            }
        }
    }

    public abstract class ListViewColumn
    {
        public event EventHandler<ListViewColumnMouseEventArgs> Click;

        protected ListViewColumn(int columnIndex)
        {
            if (columnIndex < 0)
                throw new ArgumentException(null, "columnIndex");

            ColumnIndex = columnIndex;
        }

        public virtual ListViewExtender Extender { get; protected internal set; }
        public int ColumnIndex { get; private set; }

        public virtual Font Font
        {
            get
            {
                return Extender == null ? null : Extender.Font;
            }
        }

        public ListView ListView
        {
            get
            {
                return Extender == null ? null : Extender.ListView;
            }
        }

        public abstract void Draw(DrawListViewSubItemEventArgs e);

        public virtual void MouseClick(MouseEventArgs e, ListViewItem item, ListViewItem.ListViewSubItem subItem)
        {
            if (Click != null)
            {
                Click(this, new ListViewColumnMouseEventArgs(e, item, subItem));
            }
        }

        public virtual void Invalidate(ListViewItem item, ListViewItem.ListViewSubItem subItem)
        {
            if (Extender != null)
            {
                Extender.ListView.Invalidate(subItem.Bounds);
            }
        }
    }

    public class ListViewColumnMouseEventArgs : MouseEventArgs
    {
        public ListViewColumnMouseEventArgs(MouseEventArgs e, ListViewItem item, ListViewItem.ListViewSubItem subItem)
            : base(e.Button, e.Clicks, e.X, e.Y, e.Delta)
        {
            Item = item;
            SubItem = subItem;
        }

        public ListViewItem Item { get; private set; }
        public ListViewItem.ListViewSubItem SubItem { get; private set; }
    }

    public class ListViewButtonColumn : ListViewColumn
    {
        private Rectangle _hot = Rectangle.Empty;

        public ListViewButtonColumn(int columnIndex)
            : base(columnIndex)
        {
        }

        public bool FixedWidth { get; set; }
        public bool DrawIfEmpty { get; set; }

        public override ListViewExtender Extender
        {
            get
            {
                return base.Extender;
            }
            protected internal set
            {
                base.Extender = value;
                if (FixedWidth)
                {
                    base.Extender.ListView.ColumnWidthChanging += OnColumnWidthChanging;
                }
            }
        }

        protected virtual void OnColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
        {
            if (e.ColumnIndex == ColumnIndex)
            {
                e.Cancel = true;
                e.NewWidth = ListView.Columns[e.ColumnIndex].Width;
            }
        }

        public override void Draw(DrawListViewSubItemEventArgs e)
        {
            if (_hot != Rectangle.Empty)
            {
                if (_hot != e.Bounds)
                {
                    ListView.Invalidate(_hot);
                    _hot = Rectangle.Empty;
                }
            }

            if ((!DrawIfEmpty) && (string.IsNullOrEmpty(e.SubItem.Text)))
                return;

            Point mouse = e.Item.ListView.PointToClient(Control.MousePosition);
            if ((ListView.GetItemAt(mouse.X, mouse.Y) == e.Item) && (e.Item.GetSubItemAt(mouse.X, mouse.Y) == e.SubItem))
            {
                ButtonRenderer.DrawButton(e.Graphics, e.Bounds, e.SubItem.Text, Font, true, PushButtonState.Hot);
                _hot = e.Bounds;
            }
            else
            {
                ButtonRenderer.DrawButton(e.Graphics, e.Bounds, e.SubItem.Text, Font, false, PushButtonState.Default);
            }
        }
    }
}

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

Mehdi LAMRANI 09.07.2012 22:04

У меня отлично работает. Единственное, что мне нужно было сделать, о чем вы не упомянули, - это добавить 2 столбца в список.

Paul Hunt 01.08.2014 01:28

но это не сработает, кроме второго столбца, как вставить кнопку, кроме второго столбца, я изменил индекс, но он не работает

office 302 26.12.2015 12:15

Привет @Simon, Спасибо за прекрасный ответ, я заменяю TextBoxRender из вашего ButtonRender. У меня все еще есть кнопка, есть идея реализовать текстовое поле?

Anirudha Gupta 18.01.2016 10:57

Странно, но это единственное место, где используется код, связанный с кнопками. Вам следует задать другой вопрос.

Simon Mourier 18.01.2016 11:10

У меня это работает, но почему при наведении курсора мыши возникает сбой в строке (когда значение [0] в 1-м столбце отображает 2 слова, одно немного поверх другого)?

Hacki 13.11.2020 15:11

@Hacki - не понимаю, что ты имеешь в виду. Может задать другой вопрос.

Simon Mourier 13.11.2020 15:43

@Hacki - убрать код из OnMouseMove, чтобы не было глюков при движении мыши

Valeriu Seremet 25.01.2021 12:23

Это настраиваемый элемент управления списком ЛУЧШИЙ для WinForms.
ObjectListView

Это похоже на самый простой ответ, с которым я столкнулся ... просто добавил ItemCommand к ListView.

См. Эту ссылку: обработать-кнопку-щелчок-событие-из-asp-net-listview-control

обсуждение идет о winforms, а не asp.net

skhurams 11.02.2013 14:20

Для того, чтобы расширитель Simon Mourier работал, отсутствует следующая строка:

extender.AddColumn(buttonAction);

Это должно выглядеть так:

ListViewExtender extender = new ListViewExtender(listSummary);
ListViewButtonColumn buttonAction = new ListViewButtonColumn(2);
buttonAction.Click += OnButtonActionClick;
buttonAction.FixedWidth = true;
extender.AddColumn(buttonAction);
ListViewButtonColumn(2); работает только для 1, но не для других цветов, поэтому работает только на ListViewButtonColumn(1);
office 302 26.12.2015 12:18

@ office302 - сначала нужно добавить столбец в listView. Если на первом месте нет столбца, то добавить столбец кнопок не получится.

FrenkyB 11.03.2020 19:26

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

Robinson 15.05.2020 13:06

Вы можете использовать GlacialList. Он позволяет вам помещать ЛЮБОЙ элемент управления в ячейку списка и прост в использовании. Вам просто нужно присоединить документ GlacialList.dll к справочной части вашего Решения. Если вы щелкните ссылку, она покажет вам, как она работает и как ее использовать, и загрузит ее.

Если у вас есть System.IO.FileNotFoundException на InitializeComponent(), просто загрузите исходный код по указанной выше ссылке, скомпилируйте и используйте этот .dll (внутри подпапки bin / Debug) в свой проект.

Вот пример того, как это выглядит:

example

Другие вопросы по теме