【WindowsForms】Visual Studioで既存フォームの追加方法

Visual StudioでWindowsForms(略称：WinForms)のWindowsアプリケーション開発において、
他のプロジェクトで作成したフォームを、新規のプロジェクトにもコピーした場合、
本来は、以下のような階層になるはずが、
通常のコードとDesigner.csファイルが分離されてしまう現象が発生したことありませんか？


**本来の階層** 
 FrmLogin.cs
  ┗ FrmLogin.Designer.cs
  ┗ FrmLogin.resx 

**コピー後の階層** 
FrmLogin.cs
FrmLogin.Designer.cs
  ┗ FrmLogin.resx 

VisualStudio2008くらいの時は、コピーしても分離しないで正常に画面が表示されたのですが、
Visual Studio2017くらいからフォームをコピーしてから上手くいかない事が多々ありました。

今回はVisual Studioで使用して、Windows Formsで制作するC#のアプリで、
既存フォームの追加方法およびDesigner.csファイルが分離した場合の対処方法をまとめました。

# 概要
**【開発環境】**
・Windows10
・Visual Studio Community 2019
[こちら](https://visualstudio.microsoft.com/ja/downloads/)でダウンロード可能です。(無料)


![VS2019_Download2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/d3ced501-8ce9-3578-4dda-48a92f3ef08b.png)

**【事前情報】**
TestSystemApp1という新規のプロジェクトに、既存プロジェクト内のログイン画面(FrmLogin)をコピーします。

![winform_designer分離_概要1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/560fda95-247f-2d71-a289-780e6a257e53.png)


#  既存フォームの追加方法

(1). ソリューションエクスプローラー内のプロジェクト名を右クリック⇒「追加(D)」⇒「既存の項目(G)」をクリック。
![winform_designer分離2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/30a8d30f-4e47-ebd7-4268-cbaba78eb267.png)

(2). 既存項目の追加ダイアログで、対象フォームのファイル一式を選択後、「追加」ボタンをクリック。
![winform_designer分離3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/76bba3c8-940a-7a41-5aed-7dc47a016d19.png)

(3). ソリューションエクスプローラーに追加された画面の階層を確認。
![winform_designer分離4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/06e5e910-1204-e902-e75d-1f4d2c50b328.png)


この時点で、元の画面が問題なく表示され、階層が正しければOKですが、
追加したログイン画面が正常に見れなくて、Designer.csも分離されている場合は、これ以降の手順を参照ください。

# 通常のソースとDesigner.cs、resxファイルが分離する場合の対処方法
## プロジェクトファイルを修正する方法

(1). 追加したフォームの内容でビルドエラーが出る場合は、エラーが出ないように修正後、「デバッグ」⇒「ソリューションのリビルド(R)」で一度リビルドする。
![winform_designer分離4_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/1c80c2f2-eabf-37a7-448b-a1ef319e7171.png)

(2). プロジェクトの格納フォルダを参照して、プロジェクトファイル(拡張子が.csproj)を探す。
![winform_designer分離5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/930f075a-c9a3-97ea-c44a-efa9bc933c32.png)

(3). プロジェクトファイルをテキストエディターで修正する。
![winform_designer分離6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/921bfe41-1fe8-ff33-1c91-bced132bf03d.png)

対象の画面名(FrmLogin)と、正常に表示されている画面(Form1)の内容を比較してみました。

**正常に表示されているForm1のソース**

```xml
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
```

**追加した画面のソース**

```xml
    <Compile Include="FrmLogin.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="FrmLogin.Designer.cs"/>
    <EmbeddedResource Include="FrmLogin.resx" />
```

Form1.Designer.csと"Form1.resxの書き方が異なることに気が付いたでしょうか？
その為、手動で正常に表示されている画面(Form1)と同じ書き方に修正します。

```xml
    <Compile Include="FrmLogin.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="FrmLogin.Designer.cs">
      <DependentUpon>FrmLogin.cs</DependentUpon>
    </Compile>
    <EmbeddedResource Include="FrmLogin.resx">
      <DependentUpon>FrmLogin.cs</DependentUpon>
    </EmbeddedResource>
```

修正のポイントは以下の2点です。


１．/>の部分を >に変更  

```
<Compile Include="FrmLogin.Designer.cs" />
↓
<Compile Include="FrmLogin.Designer.cs" >
```
２．DependentUponのタグ内にソース名を記載後、
Compileタグ、resxの場合は、EmbeddedResourceタグで閉じる。

```
    <Compile Include="FrmLogin.Designer.cs">
      <DependentUpon>FrmLogin.cs</DependentUpon>
    </Compile>
    <EmbeddedResource Include="FrmLogin.resx">
      <DependentUpon>FrmLogin.cs</DependentUpon>
    </EmbeddedResource>
```


(4). Visual Studioの画面に戻ると、以下のようなメッセージが表示される為、「すべて再読み込み(A)」をクリックする。
![winform_designer分離7_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/5c49415c-8fb9-b9b0-df08-7bb75063e363.png)

(5). 画面が正常に表示されて、FrmLoginの下にDesigner.csとresxが入っていればOKです。
![winform_designer分離7_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/61c3be4d-b260-d66f-6f0a-68cf831b2dfd.png)

★実際の修正中の動画になります。
<iframe width="100%" height="400" src="https://www.youtube.com/embed/BjO0Uv4VFC4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## 新規画面追加後、コードを修正する方法

もう一つの方法は、新規にフォームを作成して、必要なソースの部分だけ修正する方法になります。

(1). ソリューションエクスプローラー内のプロジェクト名を右クリック⇒「追加(D)」⇒「Windowsフォーム(F)」をクリック。

![winform_designer分離8_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/7f71492a-b82a-783b-a45c-da37fd12fb23.png)

(2). 「フォーム(Windowsフォーム)」を選択後、名前を設定して、「追加」ボタンをクリックする。
<font color="red">※名前は、元のソース名と同じにする。</font>
![winform_designer分離8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/4cabb641-5742-2002-693a-0111282dcb1c.png)

(3). ソリューションエクスプローラーで追加した画面のファイル(FrmLogin.cs)を右クリック→「コードの表示(C)」をクリックする。
![winform_designer分離9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/15a19d03-21e2-61a0-1b2b-d30b145eeae5.png)

(4). 元のプロジェクトから元のソース(FrmLogin.cs) のソースをコピー＆ペーストする。
<font color="red">※namespaceの部分だけは変更せず、今回のプロジェクト名に変更する。</font>
![winform_designer分離11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/e3c912e6-cbf5-bd68-b177-2c963fc4dc56.png)

(5). 元のプロジェクトの画面のDesigner.csを開いて、namespaceを除いた部分をコピーする。
![winform_designer分離12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/33cab908-8104-41f1-9fde-7a0aeecb9279.png)


(6). コピーした内容を、今回のプロジェクトの画面のDesigner.csにnamespaceを除いた部分にペーストする。
![winform_designer分離13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/fe7374e4-de0c-f18a-7991-e92bad19466d.png)


(7). 結果を確認して、FrmLoginの下にDesigner.csとresxが入っていればOKです。
![winform_designer分離7_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634715/61c3be4d-b260-d66f-6f0a-68cf831b2dfd.png)

★実際の修正中の動画になります。
<iframe width="100%" height="400" src="https://www.youtube.com/embed/jQPDZKTHmF4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
# まとめ

以前は既存フォームを追加しても、Designerファイルが分離する事はなかったので、
恐らくVisual Studioの問題かと思いますが、はっきりした原因は不明です。

もし既存フォームを追加した場合に、
画面のファイルが分離してしまった場合は、今回の2通りの方法からやりやすい方で、試してみてください。

# 参考
[VisualStudio2017 C#で通常のコードとDesignerが分離してしまう](https://ja.stackoverflow.com/questions/52764/visualstudio2017-c%e3%81%a7%e9%80%9a%e5%b8%b8%e3%81%ae%e3%82%b3%e3%83%bc%e3%83%89%e3%81%a8designer%e3%81%8c%e5%88%86%e9%9b%a2%e3%81%97%e3%81%a6%e3%81%97%e3%81%be%e3%81%86)