入力デバイスとしてバーコードスキャナーを使用するプログラムがあるため、テキストボックスに焦点を合わせる必要があります。
プログラムにはリストビューコントロールがあり、特定のバーコードがスキャンされるときにプログラムで項目の1つを選択します。行の背景色を設定するには:
_listviewitem.BackColor = Color.LightSteelBlue;
_
私が試したもの:
listview.HideSelection
_をfalseに設定listview.Focus()
を呼び出しますlistviewitem.Focused
_をtrueに設定listview.Invalidate
_を呼び出しますlistview.Update()
を呼び出しますlistview.Refresh()
を呼び出しますまた、タイマーで上記のものを組み合わせて、異なるスレッドで呼び出されるようにしましたが、まだ成功していません。
何か案は?
詳細:
以下を実行して1つの項目を選択します。
_listView1.Items[index].Selected = true;
_
フォーカスは常にテキストボックスにあります。
私はテキストボックスに焦点を当てるためにこのコードを持っています:
_private void txtBarcode_Leave(object sender, EventArgs e)
{
this.txtBarcode.Focus();
}
_
私の問題をシミュレートするには、そのコードをテキストボックスに追加する必要があります。
説明したとおりに動作しますexactly期待どおり、HideSelection
コントロールのListView
プロパティをFalseに設定したと仮定します。デモ用のスクリーンショットを次に示します。空のプロジェクトを作成し、ListView
コントロールとTextBox
コントロールをフォームに追加し、いくつかのサンプル項目をListView
に追加し、ビューを「詳細」に設定しました(ただし、任意のビュー)、およびHideSelection
をfalseに設定します。質問で示したようにTextBox.Leave
イベントを処理し、名前がListViewItem
に入力されるたびに対応するTextBox
を選択する簡単なロジックを追加しました。 「テスト項目6」がListView
:で選択されていることに注意してください
さて、最初に疑ったように、自分でBackColor
プロパティを設定することで気が狂うと混乱するでしょう。コントロールがデフォルトの選択色を使用してデフォルトで選択された項目を示すため、なぜこれを行う必要があるのかわかりません。 differentの色を使用したい場合は、Windowsのテーマを変更する必要があります。それを行うためのコードを記述する必要はありません。
実際、既存のコードに加えてitem.BackColor = Color.LightSteelBlue
行を追加して、ListViewItem
に入力した名前に対応するTextBox
を選択すると、exactlyになります。上記と同じもの。アイテムの背景色は、コントロールにフォーカスを設定するまで変わりません。これはexpectedの動作です。選択されたアイテムは、親コントロールがフォーカスされていない場合とフォーカスが合っている場合の外観が異なるためです。フォーカスされたコントロール上の選択されたアイテムは、システムのハイライトカラーでペイントされます。フォーカスされていないコントロール上の選択されたアイテムは、システムの3Dカラーでペイントされます。そうしないと、ListView
コントロールにフォーカスがあるかどうかを判断できません。さらに、BackColor
コントロールにフォーカスがある場合、オペレーティングシステムはカスタムListView
プロパティを完全に無視にします。背景は、デフォルトのシステムハイライトカラーでペイントされます。
もちろん、ListView
コントロールに明示的にフォーカスを設定すると、カスタム背景色がListViewItem
に適用され、物事は私が持っている配色と非常に対照的な色でレンダリングされます私のコンピューターで選択されている(すべてのユーザーがデフォルトを使用しているわけではないことに注意してください)。ただし、問題はすぐに明らかになります。TextBox.Leave
イベントハンドラメソッドで記述したコードのため、ListView
コントロールにフォーカスを設定できません!
フォーカスを変更するイベントにフォーカスを設定することは、間違ったことです。それはあなたがそのようなことをすることを許可されていないWindowsの難しいルールであり、そして documentation はあなたにexplicitlyもしないことを警告します。おそらく、あなたの答えは「私がしなければならない」の線に沿ったものになるでしょうが、それは言い訳にはなりません。すべてが期待どおりに機能していれば、そもそもこの質問をすることはないでしょう。
ならどうしよう? アプリケーションの設計が壊れています。修正することをお勧めします。アイテムが選択されていることを示すためにBackColor
プロパティを自分で設定しようとしないでください。 Windowsが選択したアイテムを強調表示するデフォルトの方法と競合します。また、フォーカスを変更するイベントでフォーカスを設定しようとしないでください。 Windowsはこれを明示的に禁止しており、ドキュメントでは、これを行うべきではないことが明確になっています。ターゲットコンピューターにマウスやキーボードがない場合、ユーザーがそれを行うためのコードを記述しない限り、ユーザーが最初に他の何かにフォーカスを設定する方法は不明です。
しかし、私はあなたがあなたのアプリケーションを修正したいと思うだろうという驚くほど小さな信仰を持っています。ドキュメントの警告を無視する人は、Q&Aサイトで善意のアドバイスを聞かない人と同じ傾向があります。だから私はあなたに骨を投げて、とにかくあなたが望む効果を得る方法を教えます。 重要な点は、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();
}
}
標準のListView
では、selected行の背景色を設定できません。選択した行の背景(および前景)色は、OSのテーマによって常に制御されます。
これを回避するには、所有者がListView
を描画する必要がありますOR ObjectListView を使用できます。ObjectListViewは.NET WinForms ListViewのオープンソースラッパーです。これにより、muchが使いやすくなり、選択した行の色を変更するなど、通常のListViewでは非常に難しいことも簡単に許可されます。
this.objectListView1.UseCustomSelectionColors = true;
this.objectListView1.HighlightBackgroundColor = Color.Lime;
this.objectListView1.UnfocusedHighlightBackgroundColor = Color.Lime;
これはObjectListViewにnotフォーカスがない場合を示しています。
以下は、複数の選択を許可せず、画像(チェックボックスなど)を持たないListViewのソリューションです。
次のようにイベントハンドラを実装します。
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();
}
注:このソリューションでは、ちらつきが発生します。これに対する修正には、保護されたプロパティDoubleBufferedをtrueに変更できるように、ListViewコントロールをサブクラス化することが含まれます。
public class ListViewEx : ListView
{
public ListViewEx() : base()
{
this.DoubleBuffered = true;
}
}
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;
}
}
}
この状況ではリストビューコントロールにフォーカスを設定できません。 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
}
}
}