Как изменить список избранных строк, даже если вы фокусируетесь на другом элементе управления?
У меня есть программа, которая использует сканер штрих-кода в качестве устройства ввода, поэтому это означает, что мне нужно сосредоточиться на текстовом поле.
Программа имеет элемент управления listview, и я выбираю один из элементов программным образом, когда сканируется определенный штрих-код. Я установил цвет фона строки следующим образом:
listviewitem.BackColor = Color.LightSteelBlue;
Вещи, которые я пробовал:
-
listview.HideSelection
установить значение false
- вызов
listview.Focus()
после установки цвета
-
listviewitem.Focused
установлено значение true
- вызов
listview.Invalidate
- вызов
listview.Update()
- вызов
listview.Refresh()
- различные комбинации указанных выше
Я также делал комбинации над материалом в таймере, так что они вызываются в другом потоке, но все равно не имеют успеха.
Любые идеи?
Дополнительная информация:
У меня есть этот код, чтобы сосредоточиться на текстовом поле:
private void txtBarcode_Leave(object sender, EventArgs e)
{
this.txtBarcode.Focus();
}
Вам нужно, чтобы текстовое поле добавляло этот код для имитации моей проблемы.
Ответы
Ответ 1
То, что вы описываете, работает точно так, как ожидалось, предполагая, что для свойства HideSelection
элемента управления ListView
установлено значение False. Вот скриншот для демонстрационных целей. Я создал пустой проект, добавил элемент управления ListView
и элемент управления TextBox
в форму, добавил некоторые примеры элементов в ListView
, установил его представление в "Детали" (хотя это работает в любом представлении) и установил HideSelection
в значение false. Я обработал событие TextBox.Leave
так же, как вы показали в вопросе, и добавил некоторую простую логику, чтобы выбрать соответствующий ListViewItem
, когда его имя было введено в TextBox
. Обратите внимание, что "Test Item Six" выбран в ListView
:
![Screenshot of test project — note that "Test Item Six" is highlighted, even though the ListView control does not have the focus.]()
Теперь, как я подозревал вначале, , вы собираетесь повредить вещи, если вы идете обезьяной с настройкой свойства BackColor
. Я не уверен, почему вы когда-либо захотите это сделать, поскольку элемент управления уже использует цвета выбора по умолчанию для указания выбранных элементов по умолчанию. Если вы хотите использовать разные цвета, вам следует изменить тему Windows, а не пытаться написать код, чтобы сделать это.
Фактически, если я добавлю строку item.BackColor = Color.LightSteelBlue
в дополнение к существующему коду, чтобы выбрать ListViewItem
, соответствующий имени, введенному в TextBox
, я получаю точно то же самое, что показано выше. Цвет фона элемента не изменяется, пока вы не установите фокус на элемент управления. То, что ожидаемое поведение, поскольку выбранные элементы выглядят по-разному, когда они имеют фокус, чем они, когда их родительский контроль не сфокусирован. Выбранные элементы сфокусированного управления окрашены цветом подсветки системы; выбранные элементы на не сфокусированных элементах управления окрашиваются системным цветом 3D. В противном случае было бы невозможно определить, имел ли фокус контроль ListView
. Более того, любое пользовательское свойство BackColor
полностью игнорируется операционной системой, когда элемент управления ListView
имеет фокус. Фон окрашивается в цвет подсветки системы по умолчанию.
Явная установка фокуса на элемент управления ListView
, конечно же, приводит к тому, что пользовательский фоновый цвет применяется к ListViewItem
, а объекты рендеринга с цветом, который очень сильно контрастирует с выбранной мной цветовой схемой на моем компьютере (помните, что не все используют значения по умолчанию). Проблема, однако, становится очевидной: вы не можете установить фокус на элемент управления ListView
из-за кода, написанного в методе обработчика событий TextBox.Leave
!
Я могу сказать вам прямо сейчас, что настройка фокуса в событии смены фокуса - это неправильная вещь. Это жесткое правило в Windows, которое вам не разрешено делать так, а документация
Итак, что теперь? Ваш дизайн приложения нарушен. Я рекомендую его исправить. Не пытайтесь обезьянью с настройкой свойства BackColor
, чтобы указать, что элемент выбран. Он конфликтует со стандартным способом, при котором Windows выделяет выбранные элементы. Кроме того, не пытайтесь установить фокус в событии смены фокуса. Windows явно запрещает это, и в документации ясно, что вы не должны это делать. Если на целевом компьютере нет мыши или клавиатуры, неясно, как пользователь будет в первую очередь устанавливать фокус на что-либо еще, если только вы не пишете код, чтобы сделать это, что вы не должны делать.
Но у меня удивительно мало веры, что вы захотите исправить свое приложение. Люди, которые игнорируют предупреждения в документации, как правило, являются теми же людьми, которые не прислушиваются к советам по вопросам Q & A. Поэтому я брошу вам кость и расскажу вам, как добиться желаемого эффекта. Ключ заключается в том, что вы не устанавливаете свойство ListViewItem
Selected
, которое позволяет избежать конфликта между вашим пользовательским BackColor
и цветом выделения по умолчанию для системы. Он также освобождает вас от необходимости явно устанавливать фокус к элементу управления ListView
и обратно (что, как мы установили выше, на самом деле не происходит, учитывая ваш метод обработчика событий Leave
). Это приводит к следующему результату:
![Fixed sample — notice the ugly blue color of the "selected" item contrasting with my current theme settings.]()
И вот код - это не очень красиво, но это всего лишь доказательство концепции, а не образец наилучшей практики:
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();
}
}
Ответ 2
Стандарт ListView
не позволяет установить цвет фона выбранной строки. Фоновые (и передние) цвета выбранной строки всегда контролируются темой ОС.
У вас есть владелец, нарисуйте ListView
, чтобы обойти это ИЛИ, вы можете использовать ObjectListView. ObjectListView - это оболочка с открытым исходным кодом в среде .NET WinForms ListView, которая упрощает ее использование много, а также позволяет легко создавать вещи, которые очень сложны в обычном ListView, например, изменяет цвета выбранных строк.
this.objectListView1.UseCustomSelectionColors = true;
this.objectListView1.HighlightBackgroundColor = Color.Lime;
this.objectListView1.UnfocusedHighlightBackgroundColor = Color.Lime;
Это показывает ObjectListView, когда он имеет не.
![enter image description here]()
Ответ 3
Вкл SelectedIndexChanged
:
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;
}
}
}
Ответ 4
Здесь решение для ListView, которое не допускает множественных выборов и
не имеет изображений (например, флажков).
- Установите обработчики событий для ListView (в этом примере он называется listView1):
- DrawItem
- Оставить (вызывается, когда фокус ListView потерян)
- Объявить глобальную переменную int (т.е. член формы, которая содержит ListView,
в этом примере он называется gListView1LostFocusItem) и присвойте ему значение -1
- int gListView1LostFocusItem = -1;
-
Реализовать обработчики событий следующим образом:
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;
}
}
Ответ 5
В этой ситуации вы не можете сосредоточиться на элементе управления списком. 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
}
}
}
Ответ 6
Просто выполните следующие действия:
- Установить свойство UnfocusedHighlighForegroundColor = "Синий"
- Установить свойство UnfocusedHighlighBackgroundColor = "White"
- Установить свойство UserCustomSelectionColors = true
Удачи:)