RetrieveVirtualItemイベントを起こすには
投稿者 るきお  (社会人)
投稿日時
2020/7/23 18:19:27
RCBさんが、どのようなプログラムをされているのかわからないので想像を交えて回答します。
選択状態と非選択状態の描画はDrawItemなどのオーナードロー用のイベントで行うのが普通で、通常RetrieveVirtualItemイベントは関係しないと思います。このあたり、何か通常ではない作り込みをされているのかもしれませんが、どのような作り込みになっているのまでは想像できませんでした。
次のプログラムでは選択されている項目は赤い文字で描画し、選択されていない項目は黒文字で描画します。
項目の上でMouseUpすると「選択時の処理」を含むメッセージボックスを表示します。
このプログラムでは選択を解除すると赤い文字ではなく黒文字で描画されます。
RCBさんが質問されているようなRetrieveVirtualItemイベントを起こす方法の回答ではないのですが、これでやりたいことは実現できますでしょうか?
選択状態と非選択状態の描画はDrawItemなどのオーナードロー用のイベントで行うのが普通で、通常RetrieveVirtualItemイベントは関係しないと思います。このあたり、何か通常ではない作り込みをされているのかもしれませんが、どのような作り込みになっているのまでは想像できませんでした。
次のプログラムでは選択されている項目は赤い文字で描画し、選択されていない項目は黒文字で描画します。
項目の上でMouseUpすると「選択時の処理」を含むメッセージボックスを表示します。
このプログラムでは選択を解除すると赤い文字ではなく黒文字で描画されます。
RCBさんが質問されているようなRetrieveVirtualItemイベントを起こす方法の回答ではないのですが、これでやりたいことは実現できますでしょうか?
Public Class Form1
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
ListView1.Dock = DockStyle.Fill 'ListViewをフォームいっぱいに広げます。
ListView1.Columns.Add("MainItem").Width = 500 '幅500のMainItem列を追加します。
ListView1.OwnerDraw = True 'オーナードローを有効にします。
ListView1.VirtualMode = True '仮想モードを有効にします。
ListView1.VirtualListSize = 1000 '仮想項目数を1000にします。
ListView1.View = View.Details '詳細モードにします。
End Sub
Private Sub ListView1_RetrieveVirtualItem(sender As Object, e As RetrieveVirtualItemEventArgs) Handles ListView1.RetrieveVirtualItem
'表示される項目のセット(毎回項目を新規作成しています。)
Dim item1 As New ListViewItem("Main" & e.ItemIndex)
e.Item = item1
End Sub
Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem
'▼背景の描画
Dim isEven As Boolean = (e.ItemIndex Mod 2 = 0)
If isEven Then
'偶数インデックスの項目は背景をベージュにします。
e.Graphics.FillRectangle(Brushes.Beige, e.Bounds)
End If
'▼文字の描画
Dim isSelected As Boolean = ListView1.SelectedIndices.Contains(e.ItemIndex)
If isSelected Then
'選択されている項目は赤い字で描画します。
e.Graphics.DrawString(e.Item.Text, ListView1.Font, Brushes.Red, e.Bounds)
Else
'選択されていない項目は既定の描画を行います。
e.DrawText()
End If
End Sub
Private Sub ListView1_MouseUp(sender As Object, e As MouseEventArgs) Handles ListView1.MouseUp
Dim mousedItem As ListViewItem = ListView1.GetItemAt(e.X, e.Y)
If mousedItem Is Nothing Then
Return
End If
MsgBox(mousedItem.Text & " 選択時の処理")
End Sub
End Class
投稿者 RCB  (社会人)
投稿日時
2020/7/23 19:35:37
るきお様、回答ありがとうございます
説明が足りなくてすみませんでした
まず、モードはラージアイコンです
MultiSelectの処理が特殊なため(Trueで修飾キー無しで複数選択出来るように)MouseUpで処理しています
でFalseの時は選択すると同時に直前の選択を解除しないといけない訳です
(なので選択/解除はSelectedIndeciesではなく完全に自前で管理しています)
その選択/解除の描画はDrawItemイベントで行っているのですがそのDrawItemイベントはRetrieveVirtualItemイベントがおきないと呼ばれません
そのRetrieveVirtualItemイベントがマウスクリック時に「クリック(選択)したアイテムの分しか」発生しません
ここで「選択解除したアイテムの分も」イベントが起こって欲しいわけです
(でないとDrawItemイベントが起きません)
DrawItemイベントが呼び出されさえすれば描画は出来ております
要はどうやってその余分なDrawItemを呼び出すか、なのです
直接呼び出せればいいんですけどねえ…(でもBoundsどうするの?って…)
説明が足りなくてすみませんでした
まず、モードはラージアイコンです
MultiSelectの処理が特殊なため(Trueで修飾キー無しで複数選択出来るように)MouseUpで処理しています
でFalseの時は選択すると同時に直前の選択を解除しないといけない訳です
(なので選択/解除はSelectedIndeciesではなく完全に自前で管理しています)
その選択/解除の描画はDrawItemイベントで行っているのですがそのDrawItemイベントはRetrieveVirtualItemイベントがおきないと呼ばれません
そのRetrieveVirtualItemイベントがマウスクリック時に「クリック(選択)したアイテムの分しか」発生しません
ここで「選択解除したアイテムの分も」イベントが起こって欲しいわけです
(でないとDrawItemイベントが起きません)
DrawItemイベントが呼び出されさえすれば描画は出来ております
要はどうやってその余分なDrawItemを呼び出すか、なのです
直接呼び出せればいいんですけどねえ…(でもBoundsどうするの?って…)
投稿者 るきお  (社会人)
投稿日時
2020/7/23 20:25:44
要するに描画したいんですよね?
Invalidateメソッドを使うとDrawItemを呼び出すことはできますが、これでは解決しませんか?
Invalidateメソッドを使うとDrawItemを呼び出すことはできますが、これでは解決しませんか?
投稿者 RCB  (社会人)
投稿日時
2020/7/23 21:39:12
すみませんでした
Invalidateでいけました
途中で一度試していたのですがチラつくので止めたのを忘れていました
お騒がせして申し訳ありませんでした
Invalidateでいけました
途中で一度試していたのですがチラつくので止めたのを忘れていました
お騒がせして申し訳ありませんでした
派生ListViewを仮想モードでオーナードローしています
選択時の処理をMouseUpイベントでしているのですが、選択状態のアイテムはRetrieveVirtualItemイベントが起きて描画されるのですが、非選択状態になったアイテムのRetrieveVirtualItemイベントが起きないため選択解除の描画が行われません
(MultiSelect=Falseです)
マウスオーバーすればRetrieveVirtualItemが呼ばれて再描画されるのですがそれでは意味がないのでMouseUpイベントの中から両方の描画を行いたいのです
何とかこのイベントを起こす方法は無いものでしょうか?…