ShiftキーやCtrl+Aで複数のitemをまとめて選択した場合、
まとめて選択される過程の一つ一つでItemSelectionChangedイベントが発生しています。
現在発生しているItemSelectionChangedイベントが、この過程のうち
「最後の一つかどうかを認識する方法」をご存知の方、アドバイスをいただければ幸いです。
といいますのは、選択内容にあわせたHTMLファイル書き出しを行う処理をしているのですが
出力させたいのは「選択された内容にあわせて」であって「選択過程の内容にあわせて」では
ないにもかかわらず、この方法がわからないので処理が重くなって悩んでいるからです。
よろしくお願いいたします。
まず、
ListView.SelectedIndices プロパティ (System.Windows.Forms)
から考えると、このイベントで「最後の一つかどうか」を判断することはできないと考えられます。
(そのような情報を判断するフラグなどの記述がない)
>選択内容にあわせたHTMLファイル書き出しを行う処理をしているのですが
これって、選択内容が変更されるたびにその都度書き出しを行う必要があるのでしょうか?
「最後の一つかどうか」を認識できたとしても、
たとえば、Ctrlキーで複数選択した場合や、Shift+下矢印などで、は、
結局行をクリックして選択範囲を増やす度に書き出しが行われるわけで、
選択途中の意図しないHTML出力が行われるのは避けられないのですが、
それは問題ないのでしょうか?
素直に考えると、選択とは別に「HTML書き出し」のボタンを用意して、
その時に、ListView.SelectedIndices を参照して、選択列を取得するのが自然じゃないかと思うのですが。
(スペックにもよりますが、その方が使用者のストレスは少なくなる気もします)
「最後の一つかどうか」を判断できないというのは、それが必要な状況が考えにくいからということでもあると思います。
で、どうしても書出しボタンは用意できないというのであれば、
たとえば「最後の選択変更から0.2秒後に書出し処理を行う」という形で、
Timerコントロール(System.Windows.Timer)を利用する方法が考えられます。
→ Timer クラス (System.Windows.Forms)
マルチスレッドとか考えなくても良さそうだし。
Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged timer1.stop() timer1.Interval=200 '<-この行はなくてもいいかも timer1.start() End Sub private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1_Tick timer1.stop() '(やりたい処理) end sub
これなら選択する度にタイマーにリセットがかかるので、
処理は軽くなるんじゃないかと思います。
ListView.SelectedIndexChanged イベント
上記リンクのVBサンプル中のSelectedIndexChangedイベントの記述にある通り、選択された複数行をコレクションとして取得可能な様です。
Private Sub ListView1_SelectedIndexChanged_UsingItems _ (ByVal sender As Object, ByVal e As System.EventArgs) _ Handles ListView1.SelectedIndexChanged Dim breakfast As ListView.SelectedListViewItemCollection = _ Me.ListView1.SelectedItems Dim item As ListViewItem Dim price As Double = 0.0 For Each item In breakfast price += Double.Parse(item.SubItems(1).Text) Next ' Output the price to TextBox1. TextBox1.Text = CType(price, String) End Sub
内容は確かではありませんが、こんな感じでしょうか。
順番が期待通りでなければ、SORTの処理を入れることになります。
Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged Dim myitems As ListView.SelectedListViewItemCollection = Me.ListView1.SelectedItems If myitems.Count = 0 Then Exit Sub Dim strMakerComment() As String = New String(myitems.Count) {} Dim i As Integer i = 0 For Each datItem As ListViewItem In myitems strMakerComment(i) = "X = " & datItem.SubItems(enmListView1.X).Text & " Y = " & datItem.SubItems(enmListView1.X).Text & vbCrLf i += 1 Next Array.Resize(strMakerComment, i + 1) If strMakerComment.Length > 0 Then vidFileReflesh(strMakerComment) ' ここでファイル書き出し End If End Sub
HALSPECIALさん、毎度ありがとうございます。
ご提案して頂いたコードでは、ListView1の中身を10件選択した場合、私がコメントで提示したプログラムと同様に
vidFileReflesh(strMakerComment)が10回呼び出されないでしょうか?
私は「選択された内容にあわせて」vidFileReflesh(strMakerComment)が1回のみ書き出し処理を
行うようにできれば、今回の件は大幅にスピードアップするのではないかと考えています。
しかし、その方法が今のところわからないので質問しています。
質問文がわかりづらくてお手数をお掛けしていますが、よろしくお願いいたします。
まず、
ListView.SelectedIndices プロパティ (System.Windows.Forms)
から考えると、このイベントで「最後の一つかどうか」を判断することはできないと考えられます。
(そのような情報を判断するフラグなどの記述がない)
>選択内容にあわせたHTMLファイル書き出しを行う処理をしているのですが
これって、選択内容が変更されるたびにその都度書き出しを行う必要があるのでしょうか?
「最後の一つかどうか」を認識できたとしても、
たとえば、Ctrlキーで複数選択した場合や、Shift+下矢印などで、は、
結局行をクリックして選択範囲を増やす度に書き出しが行われるわけで、
選択途中の意図しないHTML出力が行われるのは避けられないのですが、
それは問題ないのでしょうか?
素直に考えると、選択とは別に「HTML書き出し」のボタンを用意して、
その時に、ListView.SelectedIndices を参照して、選択列を取得するのが自然じゃないかと思うのですが。
(スペックにもよりますが、その方が使用者のストレスは少なくなる気もします)
「最後の一つかどうか」を判断できないというのは、それが必要な状況が考えにくいからということでもあると思います。
で、どうしても書出しボタンは用意できないというのであれば、
たとえば「最後の選択変更から0.2秒後に書出し処理を行う」という形で、
Timerコントロール(System.Windows.Timer)を利用する方法が考えられます。
→ Timer クラス (System.Windows.Forms)
マルチスレッドとか考えなくても良さそうだし。
Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged timer1.stop() timer1.Interval=200 '<-この行はなくてもいいかも timer1.start() End Sub private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1_Tick timer1.stop() '(やりたい処理) end sub
これなら選択する度にタイマーにリセットがかかるので、
処理は軽くなるんじゃないかと思います。
khazad-Leftyさん、コメントでタイマーを指摘してくださったtakntさんありがとうございます。
教えて頂いた方法でかなり高速化になりました。ありがとうございます。
ファイルの書き換え処理は、webbrowserコンポーネントで表示する画面の書き換えで使いたかったのですが
自分で書き換え部分をbackgroundコンポーネントでスレッド化したときに、webbrowserコンポーネントに関連する
例外が多発して挫折した経験がありました。
その為Timerクラスを折角提示していただいても、てっきり形を変えたスレッド処理だと
思いこんでいたのですが、食わず嫌いはいけないですねorz
本当にありがとうございました!
khazad-Leftyさん、コメントでタイマーを指摘してくださったtakntさんありがとうございます。
教えて頂いた方法でかなり高速化になりました。ありがとうございます。
ファイルの書き換え処理は、webbrowserコンポーネントで表示する画面の書き換えで使いたかったのですが
自分で書き換え部分をbackgroundコンポーネントでスレッド化したときに、webbrowserコンポーネントに関連する
例外が多発して挫折した経験がありました。
その為Timerクラスを折角提示していただいても、てっきり形を変えたスレッド処理だと
思いこんでいたのですが、食わず嫌いはいけないですねorz
本当にありがとうございました!