完善C#ListView系列-可编辑单元格希望是在 ListView 中双击某单元格时,该单元格内容可编辑。
不过 ListView 本⾝是不带这个功能的,我们要实现的原理是获取双击的是哪个单元格,然后在该单元格显⽰⼀个⽂本框(也可以是其他控件,本⽂以⽂本框为例)。
ListViewCell
namespace Yulin.YWinForm
{
public class ListViewCell
{
/// <summary>
/// 单元格所在的⾏。
/// </summary>
public ListViewItem Item { get; set; }
/// <summary>
/// Item 的 Index 值会变成 -1,暂时未到原因,⽤这个代替。
/// </summary>
public int ItemIndex { get; set; }
/// <summary>
/// 单元格所在的列。
submitting/// </summary>
public ColumnHeader Column { get; set; }
/// <summary>
/// 单元格相对于 ListView 的⼤⼩和位置。
/// </summary>
public Rectangle Bounds { get; set; }
}
public class ListViewCellLocator
{
[DllImport("user32")]
public static extern int GetScrollPos(int hwnd, int nBar);
/// <summary>
/// 根据位置 x、y 获得 ListViewCell。
/// </summary>
/// <param name="listView"></param>
/// <param name="x">⼯作区坐标表⽰的 x 轴坐标。</param>
/
// <param name="y">⼯作区坐标表⽰的 y 轴坐标。</param>
/// <returns></returns>
public static ListViewCell GetCell(ListView listView, int x, int y)
{
ListViewCell cell = new ListViewCell();
// 获得单元格所在的⾏。
cell.Item = listView.GetItemAt(x, y);
if (cell.Item == null)
{
return null;
}
cell.ItemIndex = cell.Item.Index; // 现在 Item.Index 还能⽤
// 根据各列宽度,获得单元格所在的列,以及 Bounds。
int currentX = cell.Item.GetBounds(ItemBoundsPortion.Entire).Left; // 依次循环各列,表⽰各列的起点值
int scrollLeft = GetScrollPos(listView.Handle.ToInt32(), 0); // 可能出现了横向滚动条,左边隐藏起来的宽度
for (int i = 0; i < listView.Columns.Count; i++)
{
if (scrollLeft + x >= currentX &&
scrollLeft + x < currentX + listView.Columns[i].Width)
scrollLeft + x < currentX + listView.Columns[i].Width)
{
cell.Column = listView.Columns[i]; // 列到了
Rectangle itemBounds = cell.Item.GetBounds(ItemBoundsPortion.Entire);
cell.Bounds = new Rectangle(currentX,
itemBounds.Y,
listView.Columns[i].Width,
itemBounds.Height);
break;
}
currentX += listView.Columns[i].Width;
}
if (cell.Column == null)
{
return null;
}
return cell;
}
}
}
<span ><strong>EditableListView</strong></span>
<span ></span><pre name="code" class="csharp">namespace Yulin {
public class EditableListViewSubmittingEventArgs : EventArgs
{
public ListViewCell Cell { get; set; }
public string Value { get; set; }
}
public delegate void EditableListViewSubmitting(object sender, EditableListViewSubmittingEventArgs e);
public class EditableListView
{
public event EditableListViewSubmitting Submitting;
private ListView ListView { get; set; }
private Point MousePosition = new Point();
private TextBox EditBox { get; set; }
public int[] TextBoxColumns { get; set; }
public EditableListView(ListView listView)
{
// 初始化 EditBox
EditBox = new TextBox();
EditBox.Visible = false;
EditBox.KeyUp += new KeyEventHandler(delegate(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
LeaveEdit();
}
else if (e.KeyCode == Keys.Enter)
{
if (Submitting != null)
{
EditableListViewSubmittingEventArgs args = new EditableListViewSubmittingEventArgs();
if (EditBox.Tag != null)
{
args.Cell = (ListViewCell)EditBox.Tag;
}
else
{
args.Cell = null;
}
args.Value = EditBox.Text;
Submitting(listView, args);
}
}
});
// 设置 ListView
ListView = listView;
ListView.MouseMove += new MouseEventHandler(delegate(object sender, MouseEventArgs e)
{
// 记录⿏标位置,便于在⿏标动作中使⽤(有些⿏标动作,⽐如双击,事件中并不传递⿏标双击时的位置)。 MousePosition.X = e.X;
MousePosition.Y = e.Y;
});
EditBox.Parent = ListView;
// 事件
ListView.DoubleClick += new EventHandler(delegate(object sender, EventArgs e)
{
ListViewCell cell = ListViewCellLocator.GetCell(this.ListView, MousePosition.X, MousePosition.Y);
if (cell == null)
{
return;
}
if (TextBoxColumns.Contains(cell.Column.Index))
{
// 设置 EditBox 的位置、⼤⼩、内容、可显⽰等。
EditBox.Bounds = cell.Bounds;
EditBox.Text = cell.Item.SubItems[cell.Column.Index].Text;
EditBox.Visible = true;
EditBox.Focus();
EditBox.Tag = cell;
}
});
}
public bool IsEditableColumn(int columnIndex)
{
if (TextBoxColumns.Contains(columnIndex))
{
return true;
}
return false;
}
public void LeaveEdit()
{
EditBox.Visible = false;
EditBox.Tag = null;
}
}
}
<span ><strong>应⽤</strong></span>
<span ><strong>
</strong></span>
<span ><stron
g>
</strong></span>
<span ></span><pre name="code" class="csharp">EditablelistViewSu {
if (e.Cell == null)
{
return;
}
int dataId = Convert.ToInt32(e.Cell.Item.SubItems[_dataIdColumn.Index].Text);
string newValue = e.Value;
// ... 更新代码省略
});
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论