メイン フォームに TabControl を持つ C# フォーム アプリケーションがあります。この TabControl は、CustomControl を含む複数の TabPages を表示するために使用されます。この CustomControl は、いくつかのボタンと PictureBox を持つ単なる Panel です。
これは、起動時のアプリの写真です。ご覧のとおり、タブ コントロール (白い領域) は空です。
ユーザーが [画像の追加] ボタンをクリックすると、画像を選択するための OpenFileDialog が表示され、選択したファイルでaddImageメソッドが呼び出されます。
private void doAddImage()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addImage(string imageFileName)
{
// Create a new bitmap and image preview custom control. Then create a new tab
// page and add the custom control to the tab page.
Bitmap bitMap = new Bitmap(imageFileName);
ImagePreviewCustomControl previewControl = new ImagePreviewCustomControl(bitMap);
previewControl.Dock = DockStyle.Fill;
TabPage tabPage = new TabPage(Path.GetFileNameWithoutExtension(imageFileName));
tabPage.Controls.Add(previewControl);
// Insert the new tab page to the right of the currently selected tab page
int selectedTabIndex = imagesTabControl.SelectedIndex;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
}
ご覧のとおり、addImageメソッドで Bitmap、CustomControl、および TabPage を作成し、それを TabControl に挿入します。
アプリケーションを起動し、[画像を追加] ボタンをクリックすると、すべて正常に動作します。
タブ ページが追加された画像を次に示します。
アプリをテストしている間、毎回 OpenFileDialog を使用して手動で画像を追加する必要はありません。そのため、コンストラクターで、テストする固定の画像ファイル名を使用してaddImageを呼び出すだけです。
public ImageViewerApp()
{
InitializeComponent();
addImage(@"C:\MyImages\Calculator-3-icon.png");
}
私が抱えている問題は、コンストラクターに画像を追加しようとすると、TabControl に表示されないことです。アプリケーションは空白で起動します (最初の写真のように)。
上記のように、アプリケーションが既に実行されているときに [画像を追加] ボタンをクリックすると、問題なく追加されます。
Createdという名前の TabControl クラスに、次のようなプロパティが見つかりました。
"Gets a value indicating whether the control has been created"
何が起こっているのかを理解するために、コンストラクターでaddImageを呼び出す直前に、Createdの値をコンソールに書き込みます。(フォーム アプリケーションをデバッグするためのカスタム コンソールがあります。)
public ImageViewerApp()
{
InitializeComponent();
TestConsole.WriteLine(imagesTabControl.Created);
addImage(@"D:\Development\Work\Other\Stardock\Start8\_downloaded\Calculator-3-icon.png");
}
コンストラクターでaddImageを呼び出す直前のCreatedの値は次のとおりです。
False
addImageメソッド内に別のコンソール出力を配置します。
private void doAddImage()
{
TestConsole.WriteLine(imagesTabControl.Created);
OpenFileDialog openFileDialog = new OpenFileDialog();
...
...
}
アプリが起動し、ユーザーが [イメージの追加] ボタンを押した後のCreatedの値は次のとおりです。
真実
コンストラクター内で TabControl がCreatedされず( InitializeComponent() 呼び出しの後でも)、アプリケーションが実行されるとCreatedになるのはなぜですか?
=更新================================================ ======================== Hans Passant の提案に基づいて、 addImageメソッドに次のコードを追加しました。
int selectedTabIndex = -1;
if (imagesTabControl.TabCount > 0)
{
selectedTabIndex = imagesTabControl.SelectedIndex;
}
else
{
selectedTabIndex = imagesTabControl.SelectedIndex + 1;
}
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
これはうまくいきません。 ================================================== =============================
=UPDATE2================================================ =======================
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
これにより、次の例外が発生します。
{"InvalidArgument=Value of '-1' is not valid for 'index'.\r\nParameter name: index"}
================================================== =============================
=UPDATE3================================================ =======================
次のコードを試しました:
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
これは例外をスローしませんが 、コンストラクターでaddImageを呼び出した後に追加されるタブ ページはありません。 ================================================== =============================
=UPDATE4================================================ =======================
コンストラクターに画像を追加することをあきらめました。代わりに、列挙型 RunMode とその型の変数 RUN_MODE を使用しています。次に、RUN_MODE == RunMode.TESTI の場合、ボタンをクリックしたときにランダムな画像を追加するメソッドを呼び出します。(OpenFileDialog は使用しません。固定ディレクトリ IMAGE_DIRECTORY 内のすべての画像ファイルを解析するだけです。
enum RunMode { NORMAL, TEST }
private static string IMAGE_DIRECTORY = @"D:\\Work\Images";
...
...
private void doAddImage()
{
if (RUN_MODE == RunMode.TEST)
{
addRandomImage();
return;
}
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addRandomImage()
{
string[] allFiles = Directory.GetFiles(IMAGE_DIRECTORY);
List<string> imageFileNames = new List<string>();
foreach (string file in allFiles)
{
bool isImageFile = Constants.Global.IMAGE_EXTENSIONS.Contains(Path.GetExtension(file));
if (isImageFile)
{
imageFileNames.Add(file);
}
}
int randomIndex = new Random().Next(imageFileNames.Count);
addImage(imageFileNames.ElementAt(randomIndex));
}
これは機能します。TEST_MODE 中に [画像を追加] ボタンをクリックすると、OpenFileDialog をスキップして、ランダムな画像を追加するだけです。
TabControl の問題を理解したいのですが、現時点では開発を続ける必要があります。私の現在のソリューションはうまく機能します。
私はすべてを理解したいと思っているので、他の人の提案を利用したいので、解決策についてこの質問を監視し続けます. ================================================== =============================