質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

ドラッグ&ドロップ

コンピューターのGUIにおいて、バーチャルなものを「つかむ」ことによって選択し、別の場所や他のバーチャルなものの上に動かす行為、またはその行為に対応していることを指す。

Q&A

解決済

3回答

2012閲覧

C# 他クラスからフォームのListBoxの表示ができない。

doro-ro

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

ドラッグ&ドロップ

コンピューターのGUIにおいて、バーチャルなものを「つかむ」ことによって選択し、別の場所や他のバーチャルなものの上に動かす行為、またはその行為に対応していることを指す。

0グッド

0クリップ

投稿2020/03/01 07:58

前提・実現したいこと

C#にて
“「実行ファイル」or「ListBox」にドラッグ&ドロップしたフォルダ内の特定フォルダを削除し、ListBoxにパスを表示する。”
C#の勉強のため作成しているのですがうまくいきません。

発生している問題・エラーメッセージ

①エラーが発生していませんが、ListBoxへの表示がうまくいきません。

②実行ファイルへドラック&ドロップされた際の書き方や、パスの渡し方これで良いのかわかりません。

C#を始めてまだ1か月程度なので、未だにインスタンスなどが理解していませんので変なコードを書いているかもしれませんが、エラーも発生していないので直し方もわかりません。
以下に書いたソースを示しますのでが教授お願いします。
特定フォルダを消す処理はまだできていませんので、コメントで書いています。

### Program.cs

C#

1 namespace WindowsFormsApp1 2{ 3 static class Program 4 { 5 /// <summary> 6 /// アプリケーションのメイン エントリ ポイントです。 7 /// </summary> 8 [STAThread] 9 static void Main() 10 { 11 string[] files = System.Environment.GetCommandLineArgs(); 12 13 if (files.Length > 1) 14 { 15 for (int i = 1; i < files.Length; i++) 16 { 17 Process processObj = new Process(); 18 processObj.Other_Process(files); 19 } 20 } 21 else 22 { 23 Application.EnableVisualStyles(); 24 Application.SetCompatibleTextRenderingDefault(false); 25 Application.Run(new Form1()); 26 } 27 28 29 } 30 } 31}

### Form1.cs

C#

1namespace WindowsFormsApp1 2{ 3 public partial class Form1 : Form 4 { 5 public Form1() 6 { 7 InitializeComponent(); 8 this.listBox1.AllowDrop = true; 9 } 10 11 private void listBox1_DragEnter(object sender, DragEventArgs e) 12 { 13 if (e.Data.GetDataPresent(DataFormats.FileDrop)) 14 { 15 e.Effect = DragDropEffects.All; 16 } 17 else 18 { 19 e.Effect = DragDropEffects.None; 20 } 21 } 22 23 private void listBox1_DragDrop(object sender, DragEventArgs e) 24 { 25 string[] fileName = 26 (string[])e.Data.GetData(DataFormats.FileDrop, false); 27 28 Process processObj = new Process(); 29 processObj.Other_Process(fileName); 30 } 31 32 public void listbox_display(string [] item) 33 { 34 listBox1.Items.AddRange(item); 35 } 36 } 37}

### Process.cs

C#

1namespace WindowsFormsApp1 2{ 3 class Process 4 { 5 public void Other_Process(string [] Path) 6 { 7 /*~~特定フォルダなどを消す処理の処理~~*/ 8 9 Form1 frm1Obj = new Form1(); 10 frm1Obj.listbox_display(Path); 11 } 12 } 13}

補足情報(FW/ツールのバージョンなど)

・Microsoft Visual Studio Professional 2019 Version 16.4.5
・Windows 10 64bit

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ProcessクラスのOther_Processメソッドで新たにForm1クラスのインスタンスを生成し、そのインスタンスでlistbox_displayメソッドを実行しても、それは今現在画面上に表示しているForm1のインスタンスではないのですから、listBox1へは作用せず、従って今表示しているリストボックスに表示されません。

ProcessクラスのOther_Processメソッドの引数でForm1を渡せるようにすれば、要望する動きになると思います。

C#

1// Process.cs 2public void Other_Process(Form1 frm1Obj, string[] Path) 3{ 4 /*~~特定フォルダなどを消す処理の処理~~*/ 5 frm1Obj.listbox_display(Path); 6}

と定義して、Form1クラスでは

C#

1// Form1.cs 2private void listBox1_DragDrop(object sender, DragEventArgs e) 3{ 4 string[] fileName = 5 (string[])e.Data.GetData(DataFormats.FileDrop, false); 6 7 Process processObj = new Process(); 8 processObj.Other_Process(this, fileName); 9}

とします。

違う話になりますが、ProcessクラスはSystem.Diagnostics.Processクラスと言うものが既にあるので、要注意です。
Process クラス - Microsoft Docs


追記しました:

いくつか他の回答もいただきましたように様々な考え方、対応方法があると思いますが、「コマンドラインオプションからファイル名を指定した場合、最初の画面表示の際に自動でリストボックスに表示する」例を書いてみましたので以下に示します。コマンドラインオプションで指定したものはForm1に新設したstring[] Filesプロパティにセットして扱うようにします。

C#

1// Program.cs 2 3using System; 4using System.Windows.Forms; 5 6namespace WindowsFormsApp1 7{ 8 static class Program 9 { 10 [STAThread] 11 static void Main() 12 { 13 Application.EnableVisualStyles(); 14 Application.SetCompatibleTextRenderingDefault(false); 15 16 var form1 = new Form1(); 17 string[] files = System.Environment.GetCommandLineArgs(); 18 if (files.Length > 1) 19 { 20 // コマンドラインオプション指定があれば、args[1]以降を取り込む。 21 var list = new System.Collections.Generic.List<string>(files); 22 list.RemoveAt(0); 23 form1.Files = list.ToArray(); 24 } 25 26 Application.Run(form1); 27 } 28 } 29}

C#

1// Form1.cs 2using System.Windows.Forms; 3 4namespace WindowsFormsApp1 5{ 6 public partial class Form1 : Form 7 { 8 // 処理対象のファイル配列プロパティ 9 public string[] Files { get; set; } 10 11 // 使いまわすので、フィールドにする。 12 private Process processObj = null; 13 14 public Form1() 15 { 16 InitializeComponent(); 17 listBox1.AllowDrop = true; 18 processObj = new Process(); 19 } 20 21 private void Form1_Load(object sender, System.EventArgs e) 22 { 23 if (Files != null && Files.Length > 0) 24 { 25 // Filesプロパティにセット済みであれば 26 // フォームの初期表示(Load)時に処理をする。 27 processObj.Other_Process(this, Files); 28 } 29 } 30 31 private void listBox1_DragEnter(object sender, DragEventArgs e) 32 { 33 if (e.Data.GetDataPresent(DataFormats.FileDrop)) 34 { 35 e.Effect = DragDropEffects.All; 36 } 37 else 38 { 39 e.Effect = DragDropEffects.None; 40 } 41 } 42 43 private void listBox1_DragDrop(object sender, DragEventArgs e) 44 { 45 Files = (string[])e.Data.GetData(DataFormats.FileDrop, false); 46 processObj.Other_Process(this, Files); 47 } 48 49 public void listbox_display(string[] item) 50 { 51 listBox1.Items.Clear(); // クリアしても良いかも 52 listBox1.Items.AddRange(item); 53 } 54 } 55}

C#

1// Process.cs 2 3namespace WindowsFormsApp1 4{ 5 class Process 6 { 7 public void Other_Process(Form1 frm1Obj, string[] Path) 8 { 9 /*~~特定フォルダなどを消す処理の処理~~*/ 10 frm1Obj.listbox_display(Path); 11 } 12 } 13}

こんな方法もある、と言う程度に参考にしてみてください。(エラーケースはほとんど考慮していません)
※他回答者であるTN8001さんも書かれていますが、質問者さんオリジナルのコードについて、もしC#含めプログラミング歴1ヶ月でそこまでできたのであれば大したものでは、と私も最初に思いました。引き続きがんばってください。

投稿2020/03/01 09:51

編集2020/03/01 13:02
dodox86

総合スコア9256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

doro-ro

2020/03/01 10:07

回答ありがとうございます。確かにインスタンスさらに新しく作成してしまうと意味ないですね。 おかげさまで表示できるようにできました。 さらに質問をして申し訳ないのですが、『Program.cs』のMainメソッドに同様に      Process processObj = new Process(); processObj.Other_Process(this, files); と記入したところ エラーCS0026 キーワード 'this' は、静的プロパティ、静的メソッド、または静的フィールド初期化子では無効です。 と表示されてしまいました。 Mainメソットはstaticなので確かにそうなのですが、同様にドラッグ&ドロップした場合でも同じような処理をしたい場合はどうすればよいでしょう?
dodox86

2020/03/01 10:23

プログラムの設計としてそもそも問題があるのですが、Mainの方を見ると、コマンドラインでファイル名を複数指定した場合は、Form1は表示されません。Form1画面を表示させるには、Application.Run(new Form1()); まで実行する必要があります。質問者さんの要望は、コマンドラインでファイル名を指定した場合、それらをドラッグ&ドロップと同様に表示させ、削除したいということでしょうか。
dodox86

2020/03/01 10:46

C#の勉強中、と言うことのなので様々なやり方があって良いと思いますが、コマンドラインからファイル名を指定した場合、「リストボックスを含んだ画面は表示せず、削除だけしてプログラムを終わる」と言う考え方もできるし、「画面表示をしたときに自動で削除し、リストボックスにも表示する。」と言う考え方もあります。後者を考えられていましたか? 現状のコードではどちらとも取れます。
dodox86

2020/03/01 13:00

追記しました。参考になれば幸いです。
doro-ro

2020/03/08 09:45

遅くなってしまい申し訳ありません。納得できました。1ヶ月で出来てすごいという言葉をいただいてとても嬉しいです。ほとんど調べて移しただけですが。。。引き続き頑張っていきたいと思います。ありがとうございました。
guest

0

最初は実行ファイルにドラッグ&ドロップの場合、画面なしかなと思いましたが出るんですね?

戻り値で消したフォルダを返すようにするといいんじゃないでしょうか。

cs:Form1.cs

1using System; 2using System.Collections.Generic; 3using System.IO; 4using System.Linq; 5using System.Windows.Forms; 6 7namespace WindowsFormsApp1 8{ 9 public partial class Form1 : Form 10 { 11 public Form1() 12 { 13 InitializeComponent(); 14 // デザイナで設定できる プロパティウィンドウ-動作 15 //this.listBox1.AllowDrop = true; 16 17 string[] files = Environment.GetCommandLineArgs(); 18 19 if(files.Length > 1) 20 { 21 Process processObj = new Process(); 22 // ↓string[]の仲間 消されたフォルダパス ↓いっこ飛ばす 23 IEnumerable<string> deleteFolders = processObj.Other_Process(files.Skip(1)); 24 listBox1.Items.AddRange(deleteFolders.ToArray()); 25 } 26 } 27 28 private void listBox1_DragEnter(object sender, DragEventArgs e) 29 { 30 // ダメな場合を先に見てreturnすると{}が減って見やすい 31 if(!e.Data.GetDataPresent(DataFormats.FileDrop)) 32 { 33 e.Effect = DragDropEffects.None; 34 return; 35 } 36 37 string[] paths = (string[])e.Data.GetData(DataFormats.FileDrop); 38 39 foreach(string path in paths) 40 { 41 // 選択にフォルダ以外(ファイル)が入っていたら禁止 42 if(!Directory.Exists(path)) 43 { 44 e.Effect = DragDropEffects.None; 45 return; 46 } 47 } 48 49 e.Effect = DragDropEffects.All; 50 } 51 52 private void listBox1_DragDrop(object sender, DragEventArgs e) 53 { 54 string[] selectFolders = (string[])e.Data.GetData(DataFormats.FileDrop, false); 55 56 Process processObj = new Process(); 57 58 // ↓string[]の仲間 消されたフォルダパス 59 IEnumerable<string> deleteFolders = processObj.Other_Process(selectFolders); 60 listBox1.Items.AddRange(deleteFolders.ToArray()); 61 } 62 } 63}

cs:Process.cs

1using System.Collections.Generic; 2using System.IO; 3using System.Linq; 4 5namespace WindowsFormsApp1 6{ 7 public class Process 8 { 9 // ↓消したフォルダを戻り値で返すように 10 public IEnumerable<string> Other_Process(IEnumerable<string> folders) 11 { 12 // ↓string[]の仲間 こちらは後から追加できる 13 List<string> deleteFolders = new List<string>(); 14 15 foreach(string folder in folders) 16 { 17 string[] subFolders; 18 try 19 { 20 // アクセスできないフォルダの場合例外 21 subFolders = Directory.GetDirectories(folder); 22 } 23 catch 24 { 25 // アクセスできないフォルダは無視 26 continue; 27 } 28 29 foreach(string subFolder in subFolders) 30 { 31 // とりあえず数字が入っているフォルダを削除するつもりになる 32 if(subFolder.Any(char.IsDigit)) 33 { 34 //DeleteDirectory(subFolder); 35 deleteFolders.Add(subFolder); 36 } 37 } 38 } 39 40 return deleteFolders; 41 } 42 43 private void DeleteDirectory(string dir) 44 { 45 // 読み取り専用ファイルがあると例外 46 // http://dobon.net/vb/dotnet/file/deletedirectory.html 47 Directory.Delete(dir, true); 48 } 49 } 50}

cs:Program.cs

1using System; 2using System.Windows.Forms; 3 4namespace WindowsFormsApp1 5{ 6 static class Program 7 { 8 [STAThread] 9 static void Main() 10 { 11 Application.EnableVisualStyles(); 12 Application.SetCompatibleTextRenderingDefault(false); 13 Application.Run(new Form1()); 14 } 15 } 16}

システムファイル等はデフォルトですと削除できず例外となります。
適切にtry catchが必要になります。
テスト中に誤って重要ファイルを消さないように十分注意してください。

1か月でここまで書けるのは素晴らしいですね(参考コードそのままだったとしてもその調査力と理解力が)

投稿2020/03/01 11:28

編集2023/07/21 08:22
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Dropだけなら、これで十分かも。

C#

1 private void listBox1_DragDrop(object sender, DragEventArgs e) 2 { 3 string[] fileName = 4 (string[])e.Data.GetData(DataFormats.FileDrop, false); 5 listBox1.Items.AddRange(fileName); 6 }

投稿2020/03/01 11:16

pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問