Ajouter un bouton dans un Listview dans WinForms

Est-il possible d'ajouter un bouton de contrôle d'une cellule à l'intérieur d'une ListView dans une application WinForms?

22
demandé sur Adam Tegen 2009-01-19 01:50:33

10 réponses

Voici un code d'une classe ListViewExtender que vous pouvez réutiliser. Ce n'est pas une classe dérivée de ListView, vous déclarez simplement qu'une colonne spécifique est affichée sous forme de boutons au lieu de texte. Le texte du bouton est le point du texte.

il permet des vues de liste de grande taille sans problèmes, n'utilise pas P/invoke, et fonctionne aussi avec des barres de défilement horizontales (certains codes proposés comme réponses ici ne le font pas ou sont assez lents avec un grand nombre d'éléments). Notez qu'il nécessite L'extension ListView pour FullRowSelecttrue et le type de vue sur Details.

voici un exemple de code qui l'utilise:

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);
        }
    }
}

voici le code ListViewExtender et les classes associées:

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);
            }
        }
    }
}
14
répondu Simon Mourier 2010-12-28 10:27:10

le ListView lui-même (ou ListViewItem) ne fonctionne pas comme un conteneur d'aucune sorte donc aucun moyen d'ajouter des contrôles directement, cependant il est faisable. J'ai utilisé cette ListView étendue avec beaucoup de succès:Intégration de Contrôles dans une ListView.

13
répondu Ryan Farley 2009-03-09 23:46:20

C'est le contrôle listview personnalisé pour WinForms.

ObjectListView

7
répondu AZ. 2011-02-25 22:44:49

Pour faire le répéteur de Simon Mourier de travail est absent de la ligne suivante:

extender.AddColumn(buttonAction);

C'est, il devrait ressembler à:

ListViewExtender extender = new ListViewExtender(listSummary);
ListViewButtonColumn buttonAction = new ListViewButtonColumn(2);
buttonAction.Click += OnButtonActionClick;
buttonAction.FixedWidth = true;
extender.AddColumn(buttonAction);
3
répondu pinker 2012-08-19 14:18:48

Peut-être que cela pourrait être d'intérêt?

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

1
répondu Dan Byström 2009-02-10 17:57:14

non, un ListView standard de Windows Forms ne supporte pas les contrôles intégrés. Vous pourriez essayer de construire votre propre contrôle personnalisé, ou vous pouvez utiliser quelque chose comme http://www.codeproject.com/KB/list/EXListView.aspx.

1
répondu walterbing1 2010-07-30 22:34:43

peut-être qu'il vaut la peine de mentionner, le contrôle de vue de liste pourrait être conçu en WPF comme un contrôle usercontrol/custom avec des boutons dans ses ListViewItems, et puis utiliser ce contrôle dans L'application WinForms, dans un ElementHost de contrôle.

1
répondu Andrei Pana 2010-12-23 08:45:50

Non Et oui, ListView lui-même ne supporte pas cette fonctionnalité, mais vous pouvez créer un bouton dessus, de sorte qu'il apparaisse à l'utilisateur comme partie intégrante de listview. (Je suppose que c'est aussi ce que fait la Visionlist Extended mentionnée ci-dessus).

0
répondu Marzena 2010-12-02 13:24:40

je suis tombé par hasard sur une discussion avant, j'espère que cette aide: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/ee232cc4-68c5-4ed3-9ea7-d4d999956504/

0
répondu Hoàng Long 2010-12-23 06:52:41

Cela ressemble à la réponse la plus simple que j'ai rencontré... juste ajouté un ItemCommandListView.

Voir ce lien: gérer-le-bouton-cliquez sur l'événement-de-un-asp-net-listview-control

-2
répondu Zwinggi 2012-07-04 07:22:21