2008年10月7日火曜日

C#でListViewをOwnerDrawで描画するときの注意事項(たぶんMSバグ)

ListView.HideSelection = False にして「他のコントロールにフォーカスが移ってもListView上の選択項目を強調表示のままにしておきたい」ことはよくありますが、このケースでOwnerDrawを実装しようとすると問題があります。ListView.OwnerDraw = Falseにして各イベントハンドラを作成しても、選択行/非選択行の背景色の描画が意図どおりにいかない方は読み進んでみてください。

OwnerDrawで背景色の描画を行う場合、DrawItemイベント及びDrawSubItemイベントの引数DrawListViewItemEventArgsStateプロパティに"Selected"フラグが付いているか否かを判別して選択行/非選択行の描画を行います(多くのサンプルソースはそうしていました)。しかし、ListView.HideSelection = False の場合、なぜかすべての行が選択行であるかのようにイベントハンドラの引数DrawListViewItemEventArgs.Stateプロパティに"Selected"フラグが付いているという現象です。ListView.HideSelectionプロパティをデフォルトのTrueに戻したところ現象が解消されたので間違いないと思います。

他にスマートでいい回避策があるのかもしれませんが、私の場合は ListViewの SelectedIndexChangedイベントで選択行をクラス変数などに保持しておき、DrawItemイベント及び DrawSubItemイベントハンドラの中で DrawListViewItemEventArgs.ItemIndexと同一の場合に選択行と判別するようにしました。

ネットで検索してもなかなかいい情報が出てこずに困っていたので、同様のお悩みを抱えている方のためにもメモ書きとして残しておきます。(というより自分用でもあるけど。)

なお、.NET Framework は 2.0 です。