Nano Hash - криптовалюты, майнинг, программирование

Как изменить цвет фона выбранной строки списка даже при фокусировке на другом элементе управления?

У меня есть программа, которая использует сканер штрих-кода в качестве устройства ввода, поэтому мне нужно сосредоточить внимание на текстовом поле.

В программе есть элемент управления списком, и я программно выбираю один из элементов при сканировании определенного штрих-кода. Я установил цвет фона строки:

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();
}

Вам нужно, чтобы текстовое поле добавляло этот код, чтобы смоделировать мою проблему.


  • Не могу понять проблему. Код listView1.Items[0].BackColor = Color.LightSteelBlue; работает хорошо. Чего вы пытаетесь достичь, но не можете? 03.03.2011
  • Мое предположение заключается в том, что выделение Windows по умолчанию перекрывает ваш пользовательский цвет фона. Сказать действительно невозможно; Ваш вопрос очень неясен, в чем заключается настоящая проблема. 03.03.2011
  • Я высветил главный ключ в проблеме. Спасибо, ребята, что посмотрели на мой вопрос. 03.03.2011

Ответы:


1

То, что вы описываете, работает в точности, как ожидалось, при условии, что вы установили для свойства HideSelection элемента управления ListView значение False. Вот скриншот для демонстрационных целей. Я создал пустой проект, добавил ListView элемент управления и TextBox элемент управления в форму, добавил несколько образцов элементов в ListView, установил для его представления значение «Подробности» (хотя это работает в любом представлении) и установил для HideSelection значение false. Я обработал событие TextBox.Leave так же, как вы показали в вопросе, и добавил некоторую простую логику для выбора соответствующего ListViewItem всякий раз, когда его имя было введено в TextBox. Обратите внимание, что в ListView: выбран "Test Item Six"

Снимок экрана тестового проекта - обратите внимание, что шестой элемент теста выделен, хотя элемент управления ListView не имеет фокуса.

Теперь, как я изначально подозревал, вы все испортите, если будете обезьянничать с настройкой свойства BackColor самостоятельно. Я не уверен, зачем вам это нужно, поскольку элемент управления уже использует цвета выбора по умолчанию для обозначения выбранных элементов по умолчанию. Если вы хотите использовать разные цвета, вам следует изменить тему Windows, а не пытаться писать код для этого.

Фактически, если я добавлю строку item.BackColor = Color.LightSteelBlue в дополнение к моему существующему коду, чтобы выбрать ListViewItem, соответствующий имени, введенному в TextBox, я получу в точности то же, что показано выше. Цвет фона элемента не изменится, пока вы не установите фокус на элемент управления. Это ожидаемое поведение, поскольку выбранные элементы в фокусе выглядят иначе, чем когда их родительский элемент управления не сфокусирован. Выбранные элементы на сфокусированных элементах управления окрашиваются в системный цвет выделения; выбранные элементы на несфокусированных элементах управления окрашиваются в системный 3D-цвет. В противном случае было бы невозможно определить, находится ли элемент управления ListView в фокусе. Более того, любое настраиваемое свойство BackColor полностью игнорируется операционной системой, когда элемент управления ListView находится в фокусе. Фон окрашивается в системный цвет выделения по умолчанию.

Явная установка фокуса на элемент управления ListView, конечно, приводит к тому, что пользовательский цвет фона применяется к ListViewItem, и вещи отображаются с цветом, который очень сильно контрастирует с цветовой схемой, которую я выбрал на своем компьютере (помните, что не все используют значения по умолчанию). Однако проблема становится очевидной сразу: нельзя установить фокус на ListView элемент управления из-за кода, который вы написали в методе обработчика событий TextBox.Leave!

Я могу сказать вам прямо сейчас, что установка фокуса в событии смены фокуса - неправильный поступок. Это жесткое правило в Windows: вам не разрешается делать подобные вещи, и документация даже предупреждает вас явно не делать этого. Предположительно, ваш ответ будет примерно таким: «Я должен», но это не оправдание. Если бы все работало должным образом, вы бы вообще не задавали этот вопрос.

И что теперь? Дизайн вашего приложения нарушен. Я предлагаю исправить это. Не пытайтесь самостоятельно установить свойство BackColor, чтобы указать, что элемент выбран. Это конфликтует со способом по умолчанию, которым Windows выделяет выбранные элементы. Кроме того, не пытайтесь установить фокус в событии, изменяющем фокус. Windows явно запрещает это, и в документации ясно сказано, что вы не должны этого делать. Если на целевом компьютере нет мыши или клавиатуры, непонятно, как пользователь собирается установить фокус на что-либо еще, если только вы не напишете код для этого, чего делать не следует.

Но я на удивление мало верю, что вы захотите исправить свое приложение. Люди, игнорирующие предупреждения в документации, как правило, те же люди, которые не прислушиваются к добрым советам на сайтах вопросов и ответов. Так что я брошу вам кость и расскажу, как в любом случае добиться желаемого эффекта. Суть заключается в том, чтобы не устанавливать свойство ListViewItem Selected, что позволяет избежать конфликта между вашим пользовательским BackColor и системным цветом выделения по умолчанию. Это также освобождает вас от необходимости явно устанавливать фокус на элемент управления ListView и обратно снова (что, как мы установили выше, на самом деле не происходит, учитывая ваш метод обработчика событий Leave). Это приведет к следующему результату:

Фиксированный образец - обратите внимание на уродливый синий цвет выбранного элемента, контрастирующий с моими текущими настройками темы.

А вот код - он не очень красивый, но это просто доказательство концепции, а не образец передового опыта:

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();
   }
}
04.03.2011
  • Ух ты - тут по частям ты немного едкий! Но в целом это хороший ответ;) 12.08.2011
  • @Vidar: Хм, поразмыслив, ты прав. Не знаю, почему я здесь так расстроился. Возможно, в ветке комментариев был расширенный обмен мнениями, который теперь удален. Или у меня просто было плохое настроение. Я не всегда такая сварливая! Но разочаровывающее количество приложений действительно ошибаются ... 12.08.2011
  • Спасибо! Сегодня утром боролся с этим пару часов. 01.02.2012
  • Мыслить творчески. 12.10.2018
  • Вдоль строк комментария Видара ... Я, вероятно, не единственный человек, который оказался здесь, потому что я хотел заставить ListBox и ListView вести себя одинаково. Несоответствующий стиль сразу же сбивает пользователей с толку. 30.06.2020
  • Любой, кто пытается применить собственные цвета к стандартным элементам управления Windows, делает это неправильно. Неудивительно, что что-то сломается. Я хочу, чтобы разработчики приложений перестали этим заниматься. Пользователи это тоже ненавидят. Мы не хотим, чтобы наши приложения выглядели ярко и по-другому. 02.07.2020

  • 2

    Стандартный ListView не позволяет вам устанавливать цвет фона выбранной строки. Цвета фона (и переднего плана) выбранной строки всегда контролируются темой ОС.

    Вы должны нарисовать свой ListView владельцем, чтобы обойти это ИЛИ вы можете использовать ObjectListView. ObjectListView - это оболочка с открытым исходным кодом для .NET WinForms ListView, которая делает его намного проще в использовании, а также позволяет легко выполнять действия, которые очень сложно выполнить в обычном ListView, например, изменять цвета выбранных строк. .

    this.objectListView1.UseCustomSelectionColors = true;
    this.objectListView1.HighlightBackgroundColor = Color.Lime;
    this.objectListView1.UnfocusedHighlightBackgroundColor = Color.Lime;
    

    Это показывает ObjectListView, когда у него нет фокуса.

    введите описание изображения здесь

    04.03.2011
  • отличная идея, но учтите, что она не работает в режиме просмотра списка; вам необходимо перейти в режим просмотра подробностей 04.05.2014

  • 3

    Вот решение для ListView, которое не допускает множественный выбор и не имеет изображений (например, флажков).

    1. Set event handlers for the ListView (in this example it's named listView1):
      • DrawItem
      • Оставить (вызывается при потере фокуса ListView)
    2. Declare a global int variable (i.e. a member of the Form that contains the ListView, in this example it's named gListView1LostFocusItem) and assign it the value -1
      • int gListView1LostFocusItem = -1;
    3. Реализуйте обработчики событий следующим образом:

      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();
      }
      

    Примечание. Это решение приведет к некоторому мерцанию. Исправление для этого включает создание подкласса элемента управления ListView, чтобы вы могли изменить защищенное свойство DoubleBuffered на true.

    public class ListViewEx : ListView
    {
        public ListViewEx() : base()
        {
            this.DoubleBuffered = true;
        }
    }
    
    14.02.2017
  • Элемент управления или форма не должны прослушивать собственные события. Просто переопределите OnDrawItem и т. Д. 14.02.2017
  • Спасибо. Легко заставить его работать с множественным выбором. Однако чистое решение, позволяющее заставить его работать с несколькими столбцами (подпунктами), остается неясным. 02.06.2020

  • 4

    В этой ситуации вы не можете сосредоточиться на элементе управления списком. txtBarcode_Leave метод предотвратит это. Но если вы хотите иметь возможность выбирать элементы списка, щелкая по ним, просто добавьте код ниже в MouseClick обработчик событий списка:

        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
                }
            }
        }
    
    03.03.2011
  • Привет, Антон, к сожалению, нет ни мыши, ни клавиатуры. 04.03.2011

  • 5

    Просто сделай так:

    1. Установить свойство UnfocusedHighlighForegroundColor = "Blue"
    2. Установить свойство UnfocusedHighlighBackgroundColor = "White"
    3. Установить свойство UserCustomSelectionColors = true

    Удачи :)

    01.08.2015
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..