




Может это может быть интересно?
Сам 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);
}
}
}
}
У меня отлично работает. Единственное, что мне нужно было сделать, о чем вы не упомянули, - это добавить 2 столбца в список.
но это не сработает, кроме второго столбца, как вставить кнопку, кроме второго столбца, я изменил индекс, но он не работает
Привет @Simon, Спасибо за прекрасный ответ, я заменяю TextBoxRender из вашего ButtonRender. У меня все еще есть кнопка, есть идея реализовать текстовое поле?
Странно, но это единственное место, где используется код, связанный с кнопками. Вам следует задать другой вопрос.
У меня это работает, но почему при наведении курсора мыши возникает сбой в строке (когда значение [0] в 1-м столбце отображает 2 слова, одно немного поверх другого)?
@Hacki - не понимаю, что ты имеешь в виду. Может задать другой вопрос.
@Hacki - убрать код из OnMouseMove, чтобы не было глюков при движении мыши
Это настраиваемый элемент управления списком ЛУЧШИЙ для WinForms.
ObjectListView
Это похоже на самый простой ответ, с которым я столкнулся ... просто добавил ItemCommand к ListView.
См. Эту ссылку: обработать-кнопку-щелчок-событие-из-asp-net-listview-control
обсуждение идет о winforms, а не asp.net
Для того, чтобы расширитель 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);@ office302 - сначала нужно добавить столбец в listView. Если на первом месте нет столбца, то добавить столбец кнопок не получится.
Я не мог заставить его работать, даже с предварительно добавленным столбцом (текстом) и вашим кодом. Не было никаких кнопок.
Вы можете использовать GlacialList. Он позволяет вам помещать ЛЮБОЙ элемент управления в ячейку списка и прост в использовании. Вам просто нужно присоединить документ GlacialList.dll к справочной части вашего Решения. Если вы щелкните ссылку, она покажет вам, как она работает и как ее использовать, и загрузит ее.
Если у вас есть System.IO.FileNotFoundException на InitializeComponent(), просто загрузите исходный код по указанной выше ссылке, скомпилируйте и используйте этот .dll (внутри подпапки bin / Debug) в свой проект.
Вот пример того, как это выглядит:
Этот код очень интересен и имеет очень удобные функции, особенно для использования во время выполнения, но мне не удалось заставить его работать, список был все еще пуст и не отображал никаких кнопок.