【发布时间】:2011-03-03 01:29:10
【问题描述】:
是否有一种简单的方法可以为列表视图添加复制粘贴,或者我应该改用 DataGridView 吗?
我的应用程序有点像地址簿,它包含电子邮件、数字等,其中复制粘贴很有用。
【问题讨论】:
标签: c# winforms listview copy-paste
是否有一种简单的方法可以为列表视图添加复制粘贴,或者我应该改用 DataGridView 吗?
我的应用程序有点像地址簿,它包含电子邮件、数字等,其中复制粘贴很有用。
【问题讨论】:
标签: c# winforms listview copy-paste
下面的示例将 Ctrl-C 作为复制到剪贴板命令,并从所有选定的行中复制第二列的值:
private void resultsListView_KeyUp(object sender, KeyEventArgs e)
{
if (sender != resultsListView) return;
if (e.Control && e.KeyCode == Keys.C)
CopySelectedValuesToClipboard();
}
private void CopySelectedValuesToClipboard()
{
var builder = new StringBuilder();
foreach (ListViewItem item in resultsListView.SelectedItems)
builder.AppendLine(item.SubItems[1].Text);
Clipboard.SetText(builder.ToString());
}
第一列使用item.Text,其他列使用item.SubItems[n].Text。
参考资料:
【讨论】:
KeyDown 事件来做到这一点。 KeyUp 不起作用,因为当按下 c 时,它会自动选择 ListBox 中以 c 开头的第一个条目,从而将我的多选呈现为一个。
builder.AppendLine(item.Text);
手动复制和粘贴并不难,只需为KeyDown(或者可能是KeyPress 不记得但相当肯定它之一)放入一个事件处理程序并检查按下了什么键查看e.KeyCode 并检查e.Control 是否为真。如果它是 x、c 或 v 之一,只需调用 Clipboard.SetText 或 Clipboard.GetText 即可在剪贴板中写入/读取。
有关 Clipboard 类的 MSDN 文档,请参阅 here。
您也可以在 ListView 上添加一个带有复制和粘贴功能的上下文菜单以使其完整。
【讨论】:
ListView 中没有单元格,切换到DataGridView 可能更容易。但是,如果您确实想坚持使用ListView,您可以对其进行处理Click 和MouseDown 事件以计算单击了哪个子项,然后更改该子项的BackColor 使其看起来被选中然后您可以处理该子项的复制和粘贴。您必须确保在项目上设置UseItemStyleForSubItems = false;,否则颜色不会显示在子项目上。
我已将其作为方法(取决于@brett 的最佳答案),因此只需在表单初始化时执行一次:copyableListView(myListView),它就会自行完成。
代码:
private void copyableListView(ListView listView)
{
listView.KeyDown += (object sender, KeyEventArgs e) =>
{
if (!(sender is ListView)) return;
if (e.Control && e.KeyCode == Keys.C)
{
var builder = new StringBuilder();
foreach (ListViewItem item in (sender as ListView).SelectedItems)
builder.AppendLine(item.Text + Environment.NewLine);
Clipboard.SetText(builder.ToString());
}
};
}
此外,在表单销毁时,您应该有删除所有订阅事件的方法,即
void myDeinit()
{
myListView=null;
myListView2=null;
...
}
【讨论】:
我的要求是添加一个按钮以将序列号列表复制到剪贴板。我以正常方式添加按钮,然后添加以下方法:
private void btnClipboard_Click(object sender, EventArgs e)
{
String clipText = string.Empty;
foreach (ListViewItem item in lstSerials.Items)
{
clipText += item.SubItems[0].Text;
clipText += Environment.NewLine;
}
if (!String.IsNullOrEmpty(clipText))
{
Clipboard.SetText(clipText);
}
}
【讨论】:
根据@Brett 的回答,我编写了这个方法,它复制整个选定的行而不是仅仅复制一列(当 FullRowSelect = true 时特别好)。
另外两个改进:
1.忽略任何换行符 - 就像 ListView 一样。
2. 未选择行时避免异常 - 只需清除剪贴板即可。
private void ListViewLogs_KeyDown(object sender, KeyEventArgs e)
{
CopySelectedRowsToClipboard(listViewLogs, e);
}
private void CopySelectedRowsToClipboard(ListView listView, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.C)
{
var builder = new StringBuilder();
foreach (ListViewItem item in listView.SelectedItems)
{
var subItems = item.SubItems.Cast<ListViewItem.ListViewSubItem>()
.Select(subItem => subItem.Text);
builder.AppendLine(string.Join(", ", subItems).Replace(Environment.NewLine, ""));
}
if (builder.Length > 0)
Clipboard.SetText(builder.ToString());
else
Clipboard.Clear();
}
}
【讨论】: