如何获取列表视图中选定的子项索引并突出显示它?

Joa*_*nge 3 .net c# listview selection winforms

我试图获取选定的 ListViewItem 索引,以便当用户单击特定行(例如第 2 行)时,我希望将单击的单元格的文本设置为 TextBox 的文本。

我还想仅突出显示此单元格,最好使用 ListView 使用的常规选择,或者我是否需要创建一个继承自 ListView 的类来执行此操作?

像这样的东西:

在此输入图像描述 在此输入图像描述

Jim*_*imi 5

您可以自己绘制选定的ListViewItem.ListViewSubItem,所有者绘制 Control (set ListView.OwnerDraw = true),然后处理该ListView.DrawSubItem事件。
\nListView.DrawColumnHeader事件可以使用默认值。

\n

\xe2\x96\xb6 我正在使用TextRenderer,因为这是默认渲染器。如果您使用Graphics.DrawText,您会注意到其中的差异。

\n
TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding |\n                        TextFormatFlags.VerticalCenter;\n\nprivate void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)\n{\n    var lv = sender as ListView;\n    var subItem = lv.HitTest(lv.PointToClient(MousePosition)).SubItem;\n\n    if (subItem != null && e.SubItem == subItem) {\n        using (var brush = new SolidBrush(SystemColors.Highlight)) {\n            e.Graphics.FillRectangle(brush, e.SubItem.Bounds);\n        }\n        TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, \n                              e.Bounds, SystemColors.HighlightText, flags);\n    }\n    else {\n        e.DrawDefault = true;\n    }\n}\n\nprivate void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e) \n    => e.DrawDefault = true;\n\n// Invalidate on a mouse interaction, otherwise the ListView doesn\'t redraw the SubItem\nprivate void listView1_MouseUp(object sender, MouseEventArgs e)\n    => (sender as ListView).Invalidate();\n
Run Code Online (Sandbox Code Playgroud)\n
\n

或者,您可以在通知鼠标交互时更改子项的颜色(此处,使用MouseDown事件)并保存先前的状态(此处仅保存颜色)。最好保存状态,因为每个 SubItem 都可以有自己的设置,因此您不能只恢复到父 ListViewItem 或 ListView 值。

\n

如前所述,UseItemStyleForSubItems = false在每个父 ListViewItem 中进行设置,否则颜色设置将被忽略。
\n此外,FullRowSelect必须设置为false,否则就没有意义:)

\n

这里,状态保存在一个名为 Tuple Field 的可为空的字段中(ListViewSubItem, Color[])
\n类对象可能更好,只是更短。

\n
private (ListViewItem.ListViewSubItem Item, Color[] colors)? previousItem = null;\n\nprivate void listView1_MouseDown(object sender, MouseEventArgs e)\n{\n    var lv = sender as ListView;\n    var subItem = lv.HitTest(e.Location).SubItem;\n\n    if (previousItem.HasValue) {\n        // If an Item\'s Colors have been changed, restore the state\n        // It removes the selection if you click in an empty area\n        previousItem.Value.Item.BackColor = previousItem.Value.colors[0];\n        previousItem.Value.Item.ForeColor = previousItem.Value.colors[1];\n        lv.Invalidate(previousItem.Value.Item.Bounds);\n    }\n\n    if (subItem != null) {\n        // Save the SubItem\'s colors state\n        previousItem = (subItem, new[] { subItem.BackColor, subItem.ForeColor });\n        // Set new Colors. Here, using the default highlight colors\n        subItem.BackColor = SystemColors.Highlight;\n        subItem.ForeColor = SystemColors.HighlightText;\n        lv.Invalidate(subItem.Bounds);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这就是这个东西的工作原理:

\n

ListView子项选择

\n
\n

\xe2\x96\xb6 关于项目/子项目索引,正如问题中提到的:

\n

当您使用ListView.HitTestListViewItem检索/单击时SubItem

\n
 var hitTest = lv.HitTest(e.Location);\n
Run Code Online (Sandbox Code Playgroud)\n

那么ListViewItem索引当然是:

\n
var itemIndex = hitTest.Item.Index;\n
Run Code Online (Sandbox Code Playgroud)\n

SubItem.Index

\n
var subItemIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);\n
Run Code Online (Sandbox Code Playgroud)\n