C# 即使焦点在另一个控件上,如何更改listview选定的行背景色?

C# 即使焦点在另一个控件上,如何更改listview选定的行背景色?,c#,winforms,listview,focus,backcolor,C#,Winforms,Listview,Focus,Backcolor,我有一个使用条形码扫描仪作为输入设备的程序,这意味着我需要将焦点放在文本框上 该程序有一个listview控件,当扫描某个条形码时,我通过编程选择其中一个项目。我通过以下方式设置行的背景色: listviewitem.BackColor = Color.LightSteelBlue; 我尝试过的事情: listview.HideSelection设置为false 设置颜色后调用listview.Focus() listviewitem.Focused设置为true 调用listview.In

我有一个使用条形码扫描仪作为输入设备的程序,这意味着我需要将焦点放在文本框上

该程序有一个listview控件,当扫描某个条形码时,我通过编程选择其中一个项目。我通过以下方式设置行的背景色:

listviewitem.BackColor = Color.LightSteelBlue;
我尝试过的事情:

  • listview.HideSelection
    设置为false
  • 设置颜色后调用
    listview.Focus()
  • listviewitem.Focused
    设置为true
  • 调用
    listview.Invalidate
  • 调用
    listview.Update()
  • 调用
    listview.Refresh()
  • 上述各项的不同组合
我也在计时器中进行了上述组合,以便在不同的线程上调用它们,但仍然没有成功

有什么想法吗

更多信息:

  • 这里的关键是控制焦点。当我选择一个项目时,listview控件没有焦点
  • 我通过执行以下操作选择一项:

    listView1.Items[index].Selected = true;
    
  • 焦点始终在文本框中

  • 计算机没有键盘或鼠标,只有条形码阅读器
我有以下代码来保持对文本框的关注:

private void txtBarcode_Leave(object sender, EventArgs e)
{
   this.txtBarcode.Focus();
}

你需要一个文本框来添加代码来模拟我的问题。

在这种情况下,你不能将焦点设置在listview控件上
txtBarcode\u Leave
方法将阻止此操作。但如果您希望能够通过单击listview项目来选择它们,只需将下面的代码添加到listview的
鼠标单击
事件处理程序即可:

    private void listView1_MouseClick(object sender, MouseEventArgs e)
    {
        ListView list = sender as ListView;

        for (int i = 0; i < list.Items.Count; i++)
        {
            if (list.Items[i].Bounds.Contains(e.Location) == true)
            {
                list.Items[i].BackColor = Color.Blue; // highlighted item
            }
            else
            {
                list.Items[i].BackColor = SystemColors.Window; // normal item
            }
        }
    }
private void listView1\u鼠标单击(对象发送者,鼠标事件目标)
{
ListView list=发送方作为ListView;
对于(int i=0;i
标准的
列表视图不允许您设置所选行的背景色。选定行的背景(和前景)颜色始终由操作系统的主题控制

您必须绘制您的
ListView
才能绕过此问题,或者您可以使用。ObjectListView是一个围绕.NET WinForms ListView的开源包装器,它使它的使用更加方便,并且可以轻松地允许在普通ListView中非常困难的事情,例如更改选定行的颜色

this.objectListView1.UseCustomSelectionColors = true;
this.objectListView1.HighlightBackgroundColor = Color.Lime;
this.objectListView1.UnfocusedHighlightBackgroundColor = Color.Lime;
当ObjectListView不具有焦点时,将显示该视图


假设您已将
ListView
控件的
HideSelection
属性设置为False,则您所描述的功能与预期完全相同。这是一个用于演示的屏幕截图。我创建了一个空白项目,在表单中添加了一个
ListView
控件和一个
TextBox
控件,在
ListView
中添加了一些示例项,将其视图设置为“Details”(尽管这在任何视图中都有效),并将
HideSelection
设置为false。我处理了
TextBox.Leave
事件,正如您在问题中所示,并添加了一些简单的逻辑来选择相应的
ListViewItem
,只要它的名称输入到
TextBox
注意,在
列表视图中选择了“测试项目6”:

现在,正如我最初怀疑的那样,如果你自己胡乱设置
BackColor
属性,你会把事情搞砸的。我不知道你为什么要这样做,因为控件已经默认使用默认选择颜色来指示所选项目。如果你想使用不同的颜色,你应该改变你的Windows主题,而不是试图写代码来做到这一点

事实上,如果我在现有代码之外添加行
item.BackColor=Color.LightSteelBlue
,以选择与键入到
文本框中的名称相对应的
ListViewItem
,我得到的结果与上面显示的完全相同。在将焦点设置为控件之前,项目的背景色不会更改。这是预期的行为,因为选定项在有焦点时与其父控件未聚焦时看起来不同。聚焦控件上的选定项使用系统高亮显示颜色绘制;未聚焦控件上的选定项将使用系统3D颜色绘制。否则,就无法判断
ListView
控件是否具有焦点。此外,当
ListView
控件具有焦点时,操作系统将完全忽略任何自定义的
BackColor
属性。背景以默认的系统高光颜色绘制

当然,显式地将焦点设置为
ListView
控件会导致自定义背景色应用于
ListViewItem
,并且渲染时的颜色与我在计算机上选择的配色方案形成鲜明对比(请记住,并非所有人都使用默认设置)。不过,问题马上变得显而易见:您无法将焦点设置到
列表视图
控件,因为您在
文本框中编写了代码。请离开
事件处理程序方法

我现在可以告诉你,在焦点改变事件中设置焦点是错误的。在Windows中,这是一条严格的规则,不允许你做这样的事情,甚至还明确警告你不要这样做。你的回答大概是“我必须”,但这不是借口。如果一切都按预期进行,那么你一开始就不会问这个问题

那么,什么不
public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();
      listView1.View = View.Details;
      listView1.HideSelection = false;
   }

   private void textBox1_TextChanged(object sender, EventArgs e)
   {
      foreach (ListViewItem item in listView1.Items)
      {
         if (item.Text == textBox1.Text)
         {
            item.BackColor = Color.LightSteelBlue;
            return;
         }
      }
   }

   private void textBox1_Leave(object sender, EventArgs e)
   {
      this.textBox1.Focus();
   }
}
    private void lBxDostepneOpcje_SelectedIndexChanged(object sender, EventArgs e)
    {

        ListViewItem item = lBxDostepneOpcje.FocusedItem as ListViewItem;
        ListView.SelectedIndexCollection lista = lBxDostepneOpcje.SelectedIndices;
        foreach (Int32 i in lista)
        {
            lBxDostepneOpcje.Items[i].BackColor = Color.White;
        }
        if (item != null)
        {
            item.Selected = false;
            if (item.Index == 0)
            {
            }
            else
            {
                lBxDostepneOpcje.Items[item.Index-1].BackColor = Color.White;
            }
            if (lBxDostepneOpcje.Items[item.Index].Focused == true)
            {
                lBxDostepneOpcje.Items[item.Index].BackColor = Color.LightGreen;
                if (item.Index < lBxDostepneOpcje.Items.Count-1)
                {
                    lBxDostepneOpcje.Items[item.Index + 1].BackColor = Color.White;
                }
            }
            else if (lBxDostepneOpcje.Items[item.Index].Focused == false)
            {
                lBxDostepneOpcje.Items[item.Index].BackColor = Color.Blue;
            }
        }

    }
private void listView1_Leave(object sender, EventArgs e)
{
    // Set the global int variable (gListView1LostFocusItem) to
    // the index of the selected item that just lost focus
    gListView1LostFocusItem = listView1.FocusedItem.Index;
}

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    // If this item is the selected item
    if (e.Item.Selected)
    {
        // If the selected item just lost the focus
        if (gListView1LostFocusItem == e.Item.Index)
        {
            // Set the colors to whatever you want (I would suggest
            // something less intense than the colors used for the
            // selected item when it has focus)
            e.Item.ForeColor = Color.Black;
            e.Item.BackColor = Color.LightBlue;

           // Indicate that this action does not need to be performed
           // again (until the next time the selected item loses focus)
            gListView1LostFocusItem = -1;
        }
        else if (listView1.Focused)  // If the selected item has focus
        {
            // Set the colors to the normal colors for a selected item
            e.Item.ForeColor = SystemColors.HighlightText;
            e.Item.BackColor = SystemColors.Highlight;
        }
    }
    else
    {
        // Set the normal colors for items that are not selected
        e.Item.ForeColor = listView1.ForeColor;
        e.Item.BackColor = listView1.BackColor;
    }

    e.DrawBackground();
    e.DrawText();
}
public class ListViewEx : ListView
{
    public ListViewEx() : base()
    {
        this.DoubleBuffered = true;
    }
}