如何在 Listview 中获取选定的 SubItem 索引并突出显示它? [英] How to get the selected SubItem index in a Listview and highlight it?

查看:22
本文介绍了如何在 Listview 中获取选定的 SubItem 索引并突出显示它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我也想只突出显示这个单元格,理想情况下使用 ListView 使用的常规选择,或者我是否需要创建一个从 ListView 继承的类来执行此操作?

像这样:

解决方案

您可以自己绘制


▶ 关于 Item/SubItem 索引,正如问题中提到的:

当您检索使用 ListView.HitTest

 var hitTest = lv.HitTest(e.Location);

那么ListViewItem索引当然是:

var itemIndex = hitTest.Item.Index;

SubItem.Index 是:

var subItemIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);

I am trying to get the selected ListViewItem index, so that when the user clicks on a particular row, such as row 2, I want the clicked cell's text to be set to a TextBox's text.

I also want to highlight only this cell, ideally using the regular selection ListView uses, or do I need to create a class that inherits from ListView to do this?

Something like this:

解决方案

You can draw yourself the ListViewItem.ListViewSubItem selected, owner-drawing the Control (set ListView.OwnerDraw = true), then handle the ListView.DrawSubItem event.
The ListView.DrawColumnHeader event can use default values.

▶ I'm using TextRenderer since this is the default renderer. If you use Graphics.DrawText, you'll notice the difference.

TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding |
                        TextFormatFlags.VerticalCenter;

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    var lv = sender as ListView;
    var subItem = lv.HitTest(lv.PointToClient(MousePosition)).SubItem;

    if (subItem != null && e.SubItem == subItem) {
        using (var brush = new SolidBrush(SystemColors.Highlight)) {
            e.Graphics.FillRectangle(brush, e.SubItem.Bounds);
        }
        TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, 
                              e.Bounds, SystemColors.HighlightText, flags);
    }
    else {
        e.DrawDefault = true;
    }
}

private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e) 
    => e.DrawDefault = true;

// Invalidate on a mouse interaction, otherwise the ListView doesn't redraw the SubItem
private void listView1_MouseUp(object sender, MouseEventArgs e)
    => (sender as ListView).Invalidate();


Or, you can change the Colors of a SubItem when a mouse interaction is notified (here, using the MouseDown event) and save the previous state (just the Colors here). It's better to save the state because each SubItem can have it's own settings, so you cannot just revert back to the Parent ListViewItem or the ListView values.

As mentioned, set UseItemStyleForSubItems = false in each parent ListViewItem, otherwise the Colors settings are ignored.
Also, FullRowSelect must be set to false, otherwise it's pointless :)

Here, the state is saved in a nullable named Tuple Field, (ListViewSubItem, Color[]).
A class object is probably better, this is just shorter.

private (ListViewItem.ListViewSubItem Item, Color[] colors)? previousItem = null;

private void listView1_MouseDown(object sender, MouseEventArgs e)
{
    var lv = sender as ListView;
    var subItem = lv.HitTest(e.Location).SubItem;

    if (previousItem.HasValue) {
        // If an Item's Colors have been changed, restore the state
        // It removes the selection if you click in an empty area
        previousItem.Value.Item.BackColor = previousItem.Value.colors[0];
        previousItem.Value.Item.ForeColor = previousItem.Value.colors[1];
        lv.Invalidate(previousItem.Value.Item.Bounds);
    }

    if (subItem != null) {
        // Save the SubItem's colors state
        previousItem = (subItem, new[] { subItem.BackColor, subItem.ForeColor });
        // Set new Colors. Here, using the default highlight colors
        subItem.BackColor = SystemColors.Highlight;
        subItem.ForeColor = SystemColors.HighlightText;
        lv.Invalidate(subItem.Bounds);
    }
}

This is how this thing works:


▶ About the Item / SubItem index, as it's mentioned in the question:

When you retrieve the ListViewItem / SubItem clicked with ListView.HitTest

 var hitTest = lv.HitTest(e.Location);

then the ListViewItem index is of course:

var itemIndex = hitTest.Item.Index;

and the SubItem.Index is:

var subItemIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);

这篇关于如何在 Listview 中获取选定的 SubItem 索引并突出显示它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆