-
Notifications
You must be signed in to change notification settings - Fork 0
/
EditableListView.cs
190 lines (171 loc) · 5.94 KB
/
EditableListView.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace Util
{
public class ListViewCell
{
///
/// 单元格所在的行。
///
public ListViewItem Item { get; set; }
///
/// Item 的 Index 值会变成 -1,暂时未找到原因,用这个代替。
///
public int ItemIndex { get; set; }
///
/// 单元格所在的列。
///
public ColumnHeader Column { get; set; }
///
/// 单元格相对于 ListView 的大小和位置。
///
public Rectangle Bounds { get; set; }
}
public class ListViewCellLocator
{
[DllImport("user32")]
public static extern int GetScrollPos(int hwnd, int nBar);
///
/// 根据位置 x、y 获得 ListViewCell。
///
///
/// 工作区坐标表示的 x 轴坐标。
/// 工作区坐标表示的 y 轴坐标。
///
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)
{
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;
}
}
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(KeyUpHandle);
EditBox.LostFocus += new EventHandler(EditBox_LostForcus);
// 设置 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(EditItem);
}
private void KeyUpHandle(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
LeaveEdit();
}
else if (e.KeyCode == Keys.Enter)
{
SaveEdit();
}
}
private void EditBox_LostForcus(object sender, EventArgs e)
{
SaveEdit();
}
private void SaveEdit()
{
if (Submitting != null)
{
EditableListViewSubmittingEventArgs args = new EditableListViewSubmittingEventArgs();
if (EditBox.Tag != null)
{
args.Cell = (ListViewCell)EditBox.Tag;
}
else
{
args.Cell = null;
}
args.Value = EditBox.Text;
LeaveEdit();
Submitting(ListView, args);
}
}
private void EditItem(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;
}
}
}