C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

DataGridViewのカスタム列セル外表示 /Mimio (18/11/29(Thu) 13:17) #89447
Re[1]: DataGridViewのカスタム列セル外表示 /魔界の仮面弁士 (18/11/29(Thu) 13:41) #89448
  └ Re[2]: DataGridViewのカスタム列セル外表示 /mimio (18/11/30(Fri) 03:48) #89458
    └ Re[3]: DataGridViewのカスタム列セル外表示 /mimio (18/11/30(Fri) 05:06) #89459 解決済み
      └ Re[4]: DataGridViewのカスタム列セル外表示 /mimio (18/11/30(Fri) 13:37) #89469 解決済み
        └ Re[5]: DataGridViewのカスタム列セル外表示 /魔界の仮面弁士 (18/11/30(Fri) 14:27) #89470
          └ Re[6]: DataGridViewのカスタム列セル外表示 /mimio (18/11/30(Fri) 18:04) #89496


親記事 / ▼[ 89448 ]
■89447 / 親階層)  DataGridViewのカスタム列セル外表示
□投稿者/ Mimio (1回)-(2018/11/29(Thu) 13:17:39)

分類:[.NET 全般] 

C# Windows Form アプリケーション(Vidual Studio 2017)
DataGridViewのカスタム列型作成に関する質問です。
(NETに関しては、自己流学習のため、ほぼ初心者ですので、よろしくお願いします。)

TimeSpanに対応する24時超(26:30など)の時刻を表示できるユーザーコントロールを作成しました。TextBox(時)+TextBox(分)+Button+(通常非表示パネル+Button群)です。Buttonは通常非表示のパネルと表示し、入退室で打刻した他の時刻を表示し、選択でTimeSpanに入れるというものです。
ユーザーコントロールとカスタムColumnはできたつもりでいましたが、実際に動かすとDataGridViewのCell内にパネルが表示されてしまいいます。

質問は、この通常非表示のパネルをセルの外に表示したいというものです。
MonthCalendarやComboBoxをカスタム列型としたときに、右ボタンをクリックするとセル外にカレンダやList部分が表示されるので、何らかの設定でできるのではないかと思っています。

よろしくお願いします。

[ □ Tree ] 返信 編集キー/

▲[ 89447 ] / ▼[ 89458 ]
■89448 / 1階層)  Re[1]: DataGridViewのカスタム列セル外表示
□投稿者/ 魔界の仮面弁士 (1958回)-(2018/11/29(Thu) 13:41:50)
No89447 (Mimio さん) に返信
> 実際に動かすとDataGridViewのCell内にパネルが表示されてしまいいます。
DataGridViewCell 継承クラスのサイズは、常にセルサイズに収まるようにします。
https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/8cd309b3-b2fc-480d-80b8-9f7cf56ecf22/


> MonthCalendarやComboBoxをカスタム列型としたときに、
> 右ボタンをクリックするとセル外にカレンダやList部分が表示されるので、
ComboBox でいえば、DropDownStyle = Simple スタイルでフォームに貼った場合、
テキスト部とリスト部を合わせた領域が、そのコントロールのサイズとして扱われますよね。

一方、DropDownStyle = DropDown / DropDownList の場合、
デザイン時、コントロールのサイズにリスト部は含まれていませんよね。


実行時で比較してみると、Simple スタイルの場合は
リスト部が親コントロール(Form など)内から出られませんが、
DropDown や DropDownList スタイルの場合には
リスト部が Form からはみ出していても表示できますよね。

これは、ドロップダウンやポップアップ表示するタイプのコントロールの場合、
追加で表示される領域は、そのコントロールの一部ではなく、
別のウィンドウが表示されているためである、と考えられます。


> 何らかの設定でできるのではないかと思っています。
パネル部はセル内に配置するのではなく、新規に Form を用意し、
そこに移動してみてください。
このフォームの TopLevel プロパティは false にしておきます(既定で false です)。

そして、TimeSpan セルがパネル入力モードになった段階で、
この子フォームを表示するようなコードを記述し、フォーカスをそこに移します。

あとは、コントロールからフォーカスが Leave したときに
そのフォームが消えるようにすれば、
ドロップダウンスタイルと同じ見た目になるかと。
[ 親 89447 / □ Tree ] 返信 編集キー/

▲[ 89448 ] / ▼[ 89459 ]
■89458 / 2階層)  Re[2]: DataGridViewのカスタム列セル外表示
□投稿者/ mimio (1回)-(2018/11/30(Fri) 03:48:56)
No89448 (魔界の仮面弁士 さん) に返信
余計なことを書くと怒られるかも知れませんが、
直接ご回答頂いたことはありませんでしたが、
以前らご高名な魔界の仮面弁士様にはお世話になっております。
今後も一層のご活躍をお祈り致します。

> ■No89447 (Mimio さん) に返信
>>実際に動かすとDataGridViewのCell内にパネルが表示されてしまいいます。
> DataGridViewCell 継承クラスのサイズは、常にセルサイズに収まるようにします。
> https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/8cd309b3-b2fc-480d-80b8-9f7cf56ecf22/

じっくりを読んでみることにします。

>>MonthCalendarやComboBoxをカスタム列型としたときに、
>>右ボタンをクリックするとセル外にカレンダやList部分が表示されるので、
> ComboBox でいえば、DropDownStyle = Simple スタイルでフォームに貼った場合、
> テキスト部とリスト部を合わせた領域が、そのコントロールのサイズとして扱われますよね。
>
> 一方、DropDownStyle = DropDown / DropDownList の場合、
> デザイン時、コントロールのサイズにリスト部は含まれていませんよね。
>
>
> 実行時で比較してみると、Simple スタイルの場合は
> リスト部が親コントロール(Form など)内から出られませんが、
> DropDown や DropDownList スタイルの場合には
> リスト部が Form からはみ出していても表示できますよね。

Simple スタイルのテストは行いませんでしたが、なるほどです。

> これは、ドロップダウンやポップアップ表示するタイプのコントロールの場合、
> 追加で表示される領域は、そのコントロールの一部ではなく、
> 別のウィンドウが表示されているためである、と考えられます。
>

別のウィンドウが表示されている?
DataGridViewCellの設定でできることではないとお考えなのですね。

>
>>何らかの設定でできるのではないかと思っています。
> パネル部はセル内に配置するのではなく、新規に Form を用意し、
> そこに移動してみてください。
> このフォームの TopLevel プロパティは false にしておきます(既定で false です)。
>
> そして、TimeSpan セルがパネル入力モードになった段階で、
> この子フォームを表示するようなコードを記述し、フォーカスをそこに移します。
>
> あとは、コントロールからフォーカスが Leave したときに
> そのフォームが消えるようにすれば、
> ドロップダウンスタイルと同じ見た目になるかと。

ユーザーコントロールに子フォームをくっつけることができるとは思いませんでした。
実際に行ってみます。
ありがとうございました。
[ 親 89447 / □ Tree ] 返信 編集キー/

▲[ 89458 ] / ▼[ 89469 ]
■89459 / 3階層)  Re[3]: DataGridViewのカスタム列セル外表示
□投稿者/ mimio (2回)-(2018/11/30(Fri) 05:06:38)
今まで、ユーザーコントロールにベタベタパネル等を貼り付けていましたが、
今回のことで、間違ったやり方であった事が分かりました。
ありがとうございました。




解決済み
[ 親 89447 / □ Tree ] 返信 編集キー/

▲[ 89459 ] / ▼[ 89470 ]
■89469 / 4階層)  Re[4]: DataGridViewのカスタム列セル外表示
□投稿者/ mimio (3回)-(2018/11/30(Fri) 13:37:38)
アローボタンクリックイベントに次のように書きました。

TimeSpanSelectForm sForm = new TimeSpanSelectForm();
sForm.TopLevel = false;
sForm.FormBorderStyle = FormBorderStyle.None;
this.Controls.Add(sForm);
sForm.Location = new Point(20, TimefLPanel.Height); //入力部のパネルの高さ分下に下げる
sForm.Show();
sForm.BringToFront();


DataGridViewでは
this.Controls.Add(sForm);
だと、thisがIDataGridViewEditingControlとなり、
DataGridViewのCell枠内に表示されるので、
this.Parent.Parent.Controls.Add(sForm);
としました。
Location位置を直せば、
this.Controls.Add(sForm);
のthisは、IDataGridViewEditingControlなので、
DataGridViewのCell内表示となりました。

解決済み
[ 親 89447 / □ Tree ] 返信 編集キー/

▲[ 89469 ] / ▼[ 89496 ]
■89470 / 5階層)  Re[5]: DataGridViewのカスタム列セル外表示
□投稿者/ 魔界の仮面弁士 (1960回)-(2018/11/30(Fri) 14:27:56)
2018/11/30(Fri) 15:04:31 編集(投稿者)

No89469 (mimio さん) に返信
> sForm.TopLevel = false;

ごめんなさい!
先の No89448 の回答で、TopLevel の true/false を逆に書いていました…。

自分のイメージしていた処理は
 sForm.TopLevel = true; // 初期値で既に true
 sForm.Deactivate += delegate { sForm.Close(); };
 sForm.Show(Form.ActiveForm);
という物です。(子コントロールとするわけではない)

Deactivate イベントは、sForm 以外の場所をクリックした場合に
キャンセル扱いとしてパネルフォームを閉じるために挿入しています。

ただしこの方法だと、ActiveForm がパネルフォーム側に移ってしまうのが難点です。

また、上記は親フォームがモードレスであることを想定しています。

ShowDialog で表示されたモーダル ウィンドウ上にある DataGridView からも
一応呼び出せますが、その場合、そのモーダルウィンドウの
呼び出し元(オーナーウィンドウ)をクリックした場合は、
Deactivate イベントが発生しません。
(モーダルフォーム自身をクリックした場合は、Deactivate が発生する)


> DataGridViewのCell枠内に表示されるので、
> this.Parent.Parent.Controls.Add(sForm);
> としました。

子コントロールとして配置する場合は、こういう風にも書けます。


DataGridView 上に配置したい場合
 // IDataGridViewEditingControl.EditingControlDataGridView プロパティ
 this.EditingControlDataGridView.Controls.Add(sForm);

親 Form 上に配置したい場合
 // Control.FindForm メソッド
 this.FindForm().Controls.Add(sForm);


ただしこの方法をとる場合、Controls.Add メソッドに渡すのは
TopLevel = false な Form ではなく、Panel 等の方が良さそうです。
[ 親 89447 / □ Tree ] 返信 編集キー/

▲[ 89470 ] / 返信無し
■89496 / 6階層)  Re[6]: DataGridViewのカスタム列セル外表示
□投稿者/ mimio (4回)-(2018/11/30(Fri) 18:04:05)
No89470 (魔界の仮面弁士 さん) に返信
> 2018/11/30(Fri) 15:04:31 編集(投稿者)
>
> ■No89469 (mimio さん) に返信
>>sForm.TopLevel = false;
>
> ごめんなさい!
> 先の No89448 の回答で、TopLevel の true/false を逆に書いていました…。
>
> 自分のイメージしていた処理は
>  sForm.TopLevel = true; // 初期値で既に true
>  sForm.Deactivate += delegate { sForm.Close(); };
>  sForm.Show(Form.ActiveForm);
> という物です。(子コントロールとするわけではない)
>
> Deactivate イベントは、sForm 以外の場所をクリックした場合に
> キャンセル扱いとしてパネルフォームを閉じるために挿入しています。
>
> ただしこの方法だと、ActiveForm がパネルフォーム側に移ってしまうのが難点です。
>
> また、上記は親フォームがモードレスであることを想定しています。
>
> ShowDialog で表示されたモーダル ウィンドウ上にある DataGridView からも
> 一応呼び出せますが、その場合、そのモーダルウィンドウの
> 呼び出し元(オーナーウィンドウ)をクリックした場合は、
> Deactivate イベントが発生しません。
> (モーダルフォーム自身をクリックした場合は、Deactivate が発生する)
>
>
>>DataGridViewのCell枠内に表示されるので、
>>this.Parent.Parent.Controls.Add(sForm);
>>としました。
>
> 子コントロールとして配置する場合は、こういう風にも書けます。
>
>
> DataGridView 上に配置したい場合
>  // IDataGridViewEditingControl.EditingControlDataGridView プロパティ
>  this.EditingControlDataGridView.Controls.Add(sForm);
>
> 親 Form 上に配置したい場合
>  // Control.FindForm メソッド
>  this.FindForm().Controls.Add(sForm);
>
>
> ただしこの方法をとる場合、Controls.Add メソッドに渡すのは
> TopLevel = false な Form ではなく、Panel 等の方が良さそうです。

いろいろな方法があるんですね。
いくつか試してみて、最も良さそうなものを探してみます。
しばらく、プログラミングから離れますので、
結果はかなり後になります。
[ 親 89447 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -