2

TabPagesは、選択されるまでTabControlでサイズ変更されないことを発見しました。これは私にとって大きな問題です。なぜなら、4つのエッジすべてに固定され、Parentプロパティを設定することで、サイズ変更可能なフォームにフィルドッキングされたTabControlのいくつかのページのうちの2つで共有されるパネルがあるからです。したがって、パネルを含まないタブを選択し、フォームのサイズを変更してから、パネル含むが現在は含まないタブを選択すると、パネルのサイズが変更されません。

パネルを固定するのではなく、塗りつぶしでドッキングしても問題ないことがわかりましたが、共有パネルはページの端まで拡張されず、サイズが異なる可能性があるため、可能な限り避けたいと思います。パネルのサイズを単に変更するのではなく、各ページのパディングサイズをいじくりまわす必要があります。

私はこれをVBとC#の両方でテストしましたが、どちらも同じように動作します。この既知のバグに対して与えられた解決策でうまくいくかもしれないと思いましたが、残念ながらそうではありません。

この問題を回避するために、ページのサイズを強制的に変更するなど、他にできることはありますか?

編集– VS 2010でこれを再現する手順:

  • TabControlをサイズ変更可能なフォームに追加し、それを塗りつぶしてドッキングし、3番目のタブを追加します。

  • パネルを3番目のタブに追加し、側面に十分なスペースを残して、4つのエッジすべてに固定し、BackColorをtabPageとは異なるものに設定して、実行時に表示できるようにします。

  • SelectedIndexChanged次のコード行をイベント に追加します。

VB

If TabControl1.SelectedIndex > 0 Then Panel1.Parent = TabControl1.SelectedTab  

C#

if (tabControl1.SelectedIndex > 0) panel1.Parent = tabControl1.SelectedTab;
  • 1番目のタブを選択した状態で、フォームを実行/デバッグし、サイズを変更します。

  • 2番目のタブを選択します–パネルのサイズが変更されていないことがわかります。

4

2 に答える 2

1

同様の問題が発生しました。C#WinformsのタブページサイズとClientSizeが間違っているを参照してください:を含む
を作成しました。のコンテンツは、の幅に基づいて配置されますが、クエリされたTabPageのは、TabPageが少なくとも1回表示されていない限り、間違っています。あなたはすでにあなたの質問に書いたように、同じことを発見しました。UserControlTabControlTabPageTabPageSizeClientSizeDisplayRectangle.Size

私が試したことは、すべて成功しませんでした。

  • それぞれのハンドルの作成を強制しますTabPage
  • プログラムでそれぞれを選択TabPage
  • visible = trueそれぞれの設定TabPage
  • PerformLayoutそれぞれに呼びかけるTabPage
  • 私がもう覚えていない他のいくつかのもの

.netが内部で何をするのか、そして各TabPageを強制的に更新するためにそれを回避する方法を見つけようとさえしましたが、複雑すぎて時間がかかるのでそれをあきらめました。

最終的に機能したもの:
私のさらなる分析は、私のUpdateLayout関数(UCのLayoutイベントによって呼び出される)にデバッグ印刷を追加しSize、TabControlと各TabPageのを印刷することでした。そして突然、私のUCは望み通りに動作しました。 これらの値のクエリは、明らかにTabPagesを更新するいくつかの.net関数をトリガーします。さらなるテストでは、UCのイベントでのクエリで十分であることが示されているため、コードに1行だけ追加する必要があります。 ClientSizeDisplayRectangle.Size
TabControl.DisplayRectangle.SizeLayout

var oSize = i_oTabControl.DisplayRectangle.Size;

おそらくコンパイラによって最適化されることを避けてください。

[MethodImpl (MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public static void TabControlForceUpdateOfTabpageSize (this TabControl i_oTabControl)
{
  if (i_oTabControl == null)
    return;
  var oSize = i_oTabControl.DisplayRectangle.Size;
}

別のテストプロジェクトでも失敗するのを見たことがあるので、あなたの状況ではうまくいかないかもしれないことを認めなければなりません。私はまだ理由を探しています。

注意:テストと開発は、.Net4.6を使用してVS2015Update3で行われました。ソリューションは、デバッグおよびリリースビルドで機能していることが確認されています。


編集:
ソリューションのテストにもう少し時間を費やしました。また、.netソースコードを再度デバッグして、そこで大まかに何が起こっているかを最終的に見つけました。

私のソリューションは、さまざまな理由の組み合わせのために機能しました:

  1. はのTabControl中に配置されますUserControl
  2. の使用サイズは、UserControl設計時のサイズとは異なります。これによりLayout、UCのイベントが発生します。
  3. サイズの変更はで発生しInitializeComponent()ます。これは、UCにまだ親がないことを意味します。
  4. それぞれTabPageに、独自のサイズではなく、のサイズを使用しています。これはSelectedTab、非表示のタブページのサイズが適切に更新されておらず、すべてのタブページのサイズが同じであることがすでにわかっているためです(AutoScroll = false)。
  5. タブページのコントロールは、選択したタブページのサイズを使用して、アンカーを介さずにプログラムで配置されます(4を参照)。

動作原理は次のとおりです。

  • 目標は、のレイアウトを強制するTabControlことTabPageです。
  • これは、実際に表示されている場合にのみ実行されます。ScrollableControl.OnVisibleChanged()`を参照してください。
  • TabPageまたはTabControlのみが表示されます。それ自体が表示に設定されていて、すべての親が表示されている場合は、を参照してくださいControl.GetVisibleCore()。コントロールがフォームに追加された場合、フォームは表示されたときに表示されるため、フォームのコンストラクターが実行されているときはコントロールは非表示になります。ただし、コントロールがまだフォームに追加されていない場合、フォームはコントロールの親ではないため、フォームの非表示は無関係になります。

「しかし、私のフォーム表示されているので、機能するはずです」と言うことになります。
はい、そうです。私の状況では、UserControlは別のTabControlの選択されていないTabPageに配置されていました。これは、UCの親が表示されていないことを意味します。ただし、サイズが変更されたとき、UCには親がありませんでした(2.および3を参照)。また、UCのイベントの回避策により、および選択されLayoutたの更新が強制される可能性があります。また、およびすべてのイベントで回避策が存在する場合でも、すべてのタブページのサイズ値は正しいものでした(少なくともいくつかのサイクルの後)。 TabControlTabPageLayoutTabControlTabPage

回避策は、ちょっとしたトリック(テスト済み)でも機能する可能性があります。
親からTabControlを削除し、すべてのタブページを循環して、後で親に追加し直します。

var oParent = tabctrlU.Parent;
oParent.Controls.Remove (tabctrlU);
var tabStart = tabctrlU.SelectedTab;
foreach (TabPage tab in tabctrlU.TabPages)
  tabctrlU.SelectedTab = tab;
tabctrlU.SelectedTab = tabStart;
oParent.Controls.Add (tabctrlU);

これにより、更新の強制が有効になります。
ただし、非表示のタブの将来のサイズ変更では機能しません。これで、サイズを変更するたびにイベントがトリガーされるLayoutため、そこにコードを追加できます。実際、タブコントロールを毎回削除して再度追加することはありません。これはばかげています。したがって、この解決策はあなたのケースにはあまり当てはまらないことを認めなければなりません。しかし、あなた(および他の人)は今、それに対処する方法についていくつかのアイデアを持っています。

すでに自分で解決策を見つけたので、最初のTabPageに移動したくない場合は、ctor内のとその親TabPagePanel1のサイズと位置を覚えて、(新規)に従ってプログラムでサイズを変更できます。選択したTabPageがそのページに移動された後のサイズ。Panel1Panel1

于 2019-06-03T12:45:46.657 に答える
0

回避策として、Hans Passantは、パネルを最初のTabPage(非表示)に配置してから、イベントハンドラーでそのVisibleプロパティを設定することを提案しました。私が説明したように、それは完全には機能しませ。起動時の「1回限りの」問題ではないからです。これは、パネルを表示しないタブが選択されているときにフォームのサイズが変更され、現在パネルが含まれていないパネルを表示するタブを選択するたびに発生しますが、答えは正しい方向を示していました。これは、選択されたタブに応じてパネルのVisibleプロパティを設定し、パネルが表示されているかどうかに関係なく、常にパネルを選択されたタブに移動します–例:

Private Sub TabControl1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles TabControl1.SelectedIndexChanged
    Panel1.Visible = (TabControl1.SelectedTab Is TabPage2) OrElse (TabControl1.SelectedTab Is TabPage3)
    Panel1.Parent = TabControl1.SelectedTab
End Sub
于 2012-07-02T13:23:12.253 に答える