tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルDataGridView上で右クリック
記事No12142
投稿日: 2024/02/10(Sat) 10:36
投稿者からしれんこん
Visual Studio 2022 Windows11 でプログラムを作成しています。

フォーム上にDaraGridViewを2つ配置し、ContextMenuを作成し右クリックでメニューを呼び出すようにしています。

一方のDataGridViewでは、特定の列を選択している時に、右クリックをしたら選択状態はそのままでメニューが表示されるのですが、

もう一方は右クリック時に選択状態がすべて解除され、メニューが表示されてしまいます。

双方のDataGridViewの設定は見比べましたが同じでした。データベースの読み込み方も同じ流れでした。
なぜ2つのDataGridViewの右クリック時に挙動が違うのかがわかりません。

何か原因がわかる方いましたらお願いします。

[ツリー表示へ]
タイトルRe: DataGridView上で右クリック
記事No12143
投稿日: 2024/02/14(Wed) 10:09
投稿者魔界の仮面弁士
> Visual Studio 2022 Windows11 でプログラムを作成しています。
ターゲット フレームワーク は何ですか?


> フォーム上にDaraGridViewを2つ配置し、ContextMenuを作成し
.NET Framework 2.0 以降の ContextMenuStrip クラスではなく、
.NET Framework 1.0 以降の ContextMenu クラスを使っているのですね?

下位互換性のために ContextMenu も残されていますが、
通常は ContextMenuStrip を使う方が一般的かと思いますよ。

 dgv1.ContextMenu = New ContextMenu()
 dgv2.ContextMenuStrip = New ContextMenuStrip()
https://dobon.net/vb/dotnet/control/menuitempopup.html


> 右クリックでメニューを呼び出すようにしています。
コンテキストメニューの呼び出しは本来、マウスの右クリックだけでなく、
キーボード右下のアプリケーション キーでの呼び出しや Shift + F10 キーなど、
複数の呼び出し方法があるはずです。右クリック以外の操作時のメニューも確認してみてください。


> もう一方は右クリック時に選択状態がすべて解除され、メニューが表示されてしまいます。
新規プロジェクトで、DataGridView にサンプルデータを表示するだけの
単純なプロジェクトを作成し、それで再現しますか?
(データベースの値では無く、固定値を読み込ませる形で良い)
再現するのであれば、そのコードを提示いただきたいです。

再現しないのであれば、元コードを解析しないと流石に分からないです。

プロパティの設定(TabIndex の入れ替えや、[手前に表示]の切り替えも含む)、
イベントの割り当て有無やその実装内容、データを読み込ませるイベント処理の実行タイミング等々、
何が要因なのかはソースを見ないと分かりません。
コードをできる限りコメントアウトしていくなどして、原因を探ってみてください。


当方で下記のコードで試してみた限りでは、選択状態が解除される事象は確認できていません。


'何もコントロールを貼っていない空のフォームの上に、検証用の DataGridView を貼ってみる
Public Class Form1
    Private WithEvents splitContainer1 As SplitContainer
    Private WithEvents dgv1 As DataGridView
    Private WithEvents dgv2 As DataGridView
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        splitContainer1 = New SplitContainer() With {.Dock = DockStyle.Fill, .Parent = Me, .Name = "splitContainer1"}
        dgv1 = New DataGridView() With {.Dock = DockStyle.Fill, .Parent = splitContainer1.Panel1, .Name = "dgv1"}
        dgv2 = New DataGridView() With {.Dock = DockStyle.Fill, .Parent = splitContainer1.Panel2, .Name = "dgv2"}
        splitContainer1.SplitterDistance = splitContainer1.Width \ 2

        dgv1.AllowUserToAddRows = False
        dgv2.AllowUserToAddRows = False
        dgv1.RowCount = 100
        dgv2.RowCount = 100
        dgv1.ColumnCount = 10
        dgv2.ColumnCount = 10
        dgv1.SelectionMode = DataGridViewSelectionMode.CellSelect
        dgv2.SelectionMode = DataGridViewSelectionMode.CellSelect
        dgv1.TopLeftHeaderCell.Value = "dgv1"
        dgv2.TopLeftHeaderCell.Value = "dgv2"
        dgv1.SelectAll()
        dgv2.SelectAll()

        '--- ContextMenu vs. ContextMenuStrip
        dgv1.ContextMenu = New ContextMenu()
        dgv2.ContextMenuStrip = New ContextMenuStrip()
        AddHandler dgv1.ContextMenu.MenuItems.Add("Test").Click, Sub() dgv1.TopLeftHeaderCell.Value = Now.ToString("HH:mm:ss.fff")
        AddHandler dgv2.ContextMenuStrip.Items.Add("Test").Click, Sub() dgv2.TopLeftHeaderCell.Value = Now.ToString("HH:mm:ss.fff")
        AddHandler dgv1.MouseUp, Sub(dgv, p) If MouseButtons.Right.HasFlag(p.Button) Then dgv1.ContextMenu.Show(dgv1, p.Location)
        AddHandler dgv1.KeyUp, Sub(dgv, p) If p.KeyCode = Keys.Apps Then dgv1.ContextMenu.Show(dgv1, New Point(dgv1.Width \ 2, dgv1.Height \ 2))
        AddHandler dgv1.KeyUp, Sub(dgv, p) If p.KeyCode = Keys.F10 AndAlso p.Shift Then dgv1.ContextMenu.Show(dgv1, New Point(dgv1.Width \ 2, dgv1.Height \ 2))
    End Sub
End Class

[ツリー表示へ]
タイトルRe^2: DataGridView上で右クリック
記事No12144
投稿日: 2024/02/14(Wed) 14:12
投稿者魔界の仮面弁士
>> 特定の列を選択している時に、右クリックをしたら選択状態は
> 当方で下記のコードで試してみた限りでは、選択状態の解除は確認できませんでした。
「特定の列を選択」とあったので、選択モードを FullColumnSelect にしたり、
コンテキストメニューの割り当てを Columns(1) と Columns(2) に限定してみたりしましたが、
やはり選択解除されてしまう事象は再現できませんでした。



'選択モードを FullColumnSelect に変更
dgv2.AllowUserToAddRows = False
dgv2.TopLeftHeaderCell.Value = "dgv2"
dgv2.RowCount = 100
dgv2.ColumnCount = 10
For c = 0 To 9
    dgv2.Columns(c).SortMode = DataGridViewColumnSortMode.Programmatic
Next
dgv2.SelectionMode = DataGridViewSelectionMode.FullColumnSelect


'コントロール全体ではなく、特定の列にだけ ContextMenuStrip をセットする
'dgv2.ContextMenuStrip = New ContextMenuStrip()

'第2列、第3列にのみ、ContextMenuStrip を割り当て
Dim ctx As ContextMenuStrip, menu As ToolStripItem
ctx = New ContextMenuStrip()
menu = ctx.Items.Add("Col2")
dgv2.Columns(1).ContextMenuStrip = ctx
AddHandler menu.Click, Sub() dgv2.Columns(1).HeaderText = Now.ToString("HH:mm:ss.fff")
ctx = New ContextMenuStrip()
menu = ctx.Items.Add("Col3")
dgv2.Columns(2).ContextMenuStrip = ctx
AddHandler menu.Click, Sub() dgv2.Columns(2).HeaderText = Now.ToString("HH:mm:ss.fff")

'2列目を選択しておく
dgv2.ClearSelection()
dgv2.Columns(1).Selected = True


>> 双方のDataGridViewの設定は見比べましたが同じでした。データベースの読み込み方も同じ流れでした。
>> なぜ2つのDataGridViewの右クリック時に挙動が違うのかがわかりません。
からしれんこんさんの現状のコードがどういう実装になっているのか、そして
プロパティ設定がどうなっているのかが分からず、今のところ再現はできていません。

動作に差異のある 2 つの DataGridView に対して、
フォーカス遷移を伴う操作(メッセージボックスの表示も含む)が発生していないか、
バインドしているデータの再割り当てや更新作業などの違いが無いか、などを確認してみましょう。
もしかしたら DataGridView そのものではなく、DataSource にバインドしている
BindingSource や DataSet などにイベント処理が含まれているという可能性も考えられます。



また、(ContextMenu ではなく)ContextMenuStrip を使っている場合には、
状況依存メニュー(現在のセルの状態や値によって表示するメニューを切り替える)に
したい場合には、CellContextMenuStripNeeded イベントが使われることもあります。
https://dobon.net/vb/dotnet/datagridview/contextmenuestrip.html

[ツリー表示へ]
タイトルRe^3: DataGridView上で右クリック
記事No12145
投稿日: 2024/02/15(Thu) 17:52
投稿者からしれんこん
情報ありがとうございます。
どこか条件が違うのか呼び出し方をもう1度見てみます。

[ツリー表示へ]