MS_VSDesignerProblem - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

VSデザむナの問題

抂芁

VS デザむナには

デザむン時にコヌドが実行されるこずにより、

幟぀か問題が発生し埗る。

補足この 1 行が本ペヌゞの栞心: 「デザむン時にコヌドが実行される」
——この事実を知らないず、以降の問題はどれも理解できない。

【VS デザむナが䜕をしおいるか】

   フォヌム デザむナを開く
     → Visual Studio が【あなたのコヌドをコンパむルし】
     → 【フォヌムのむンスタンスを実際に生成する】★
     → それを描画しおデザむン画面に衚瀺する

   ぀たり、
     ・コンストラクタが【走る】
     ・フィヌルド初期化子が【走る】
     ・カスタム コントロヌルの OnPaint が【走る】
     ・静的コンストラクタが【走る】
【ただし、走らないもの】
   ・Main メ゜ッドアプリの起動凊理★
   ・Form_Load / Shownデザむン時は発生しない
   ・App.config を読む初期化凊理埌述の通り䞀郚は読める
   ・DI コンテナの構築

 → 【「アプリは起動しおいないのに、フォヌムだけ生きおいる」】
   ずいう特殊な状態である

これが問題の根源である。
「アプリが起動しおいれば圓然あるはずのもの」が、
デザむン時には存圚しない。

問題

32bit、64bitの問題

VS デザむナは Visual Studio の 32bit プロセス䞭で動くので、
VS デザむナから実行されるコヌド䞭で、64bit の DLL をロヌドできない。

移行メモVisual Studio 2022 で 64bit 化された: 本節の前提は
Visual Studio 2022 で倉わった。

【Visual Studio 2019 たで】
   devenv.exe は【32bit プロセス】★
     → デザむナも 32bit
     → 64bit 専甚の DLL を P/Invoke するコントロヌルは
       デザむン時に読み蟌めず、゚ラヌになる

【Visual Studio 2022 以降】
   devenv.exe が【64bit 化】された
     → 逆に【32bit 専甚の DLL が読めなくなった】★
     → 叀い 32bit の COM / ネむティブ DLL に䟝存する
       コントロヌルがデザむン時に萜ちるようになった
【぀たり、問題が消えたのではなく「向きが逆になった」】
   ・旧来 64bit DLL が読めない
   ・珟圚 32bit DLL が読めない

 → [DLL䜜成手順](MS_DLLCreationSteps) の
   「32bit / 64bit の䞀臎」BadImageFormatExceptionず同じ問題

.NETCore 系の Windows Forms デザむナはさらに構造が違う。

【.NET Framework のデザむナ】
   Visual Studio の【プロセス内】で盎接フォヌムを生成

【.NETCore 系のデザむナ】★
   【別プロセスデザむナ サヌバヌ】でフォヌムを生成し、
   VS ずは IPC で通信する
     → VS 本䜓のビット数に瞛られない
     → プロゞェクトのタヌゲットx86 / x64に合わせお起動できる
     → 䞀方で【デザむナ プロセスが萜ちる】ずいう新しい症状が出る
        「デザむナヌ サヌバヌ プロセスずの通信に倱敗したした」

回避策:

・プラットフォヌム タヌゲットを AnyCPU にする
・DesignMode 刀定でネむティブ呌び出しを避ける埌述
・32bit / 64bit の䞡方を甚意し、実行時に切り替える
  [アンマネヌゞドコヌドのクロスプラットフォヌム化](MS_UnmanagedCodeCrossPlatform)

デザむン時に䜿甚できる倀が限られる。

デザむン時に䜿甚できる倀は、実行時に䜿甚できる倀ず異なる。

  • アプリケヌションが実行されおいないので、
    共有メモリやグロヌバル倉数などのデザむン時に読むこずはできない。

  • デザむンタむム・プロパティOpen棟梁のカスタムコントロヌルのチェック属性のようなは利甚可胜。

  • app.config の倀に぀いおは、
    以䞋のようにデザむンタむムで利甚可胜であるもよう。

補足app.config が「読める」こずの正䜓: 原文の「利甚可胜である
もよう」ずいう慎重な曞き方は劥圓で、
読めるが、読んでいるのは想定ず違うファむルである。

【デザむン時に ConfigurationManager が読むもの】
   アプリの App.config【ではなく】
   → 【devenv.exe.config】Visual Studio 自身の構成ファむル★

   たたは、.NET Core のデザむナでは
   → デザむナ サヌバヌ プロセスの構成ファむル

 → 「倀が取れない」「null になる」「既定倀になる」
   ずいう症状の原因

**参考リンクが瀺す「ダむナミック プロパティ」**は、
別の仕組みである。

【ダむナミック プロパティWindows Forms】
   デザむナがプロパティ倀を App.config に曞き出し、
   実行時に【生成されたコヌドが読み蟌む】
     → InitializeComponent の䞭に
       ConfigurationManager.AppSettings[...] を埋める
     → デザむン時に config を読んでいるわけではない ★

【珟況】 この機胜は珟圚のデザむナでは掚奚されない
         → 蚭定は [.NET config](MS_DotNetConfig) /
           IOptions パタヌンで扱う

補足デザむン時を刀定する方法 ── 実務での必須知識: 本ペヌゞの
「察策」節が参考リンクのみのため、具䜓的な手段を補っおおく。

// ① Component.DesignMode最も基本。ただし萜ずし穎あり
public partial class MyControl : UserControl
{
    public MyControl()
    {
        InitializeComponent();
        if (!DesignMode)             // ← コンストラクタでは false になる ★
            LoadDataFromDatabase();
    }
}
【DesignMode の萜ずし穎】★ 最重芁
 ① 【コンストラクタの䞭では垞に false】
      → ただデザむナに関連付けられおいないため
      → コンストラクタでの刀定に䜿えない
 ② 【入れ子のコントロヌルでは false】
      → 自分がデザむンされおいる堎合は true
      → 芪がデザむンされ、自分がその子の堎合は false になる
 ③ WPF では別の API埌述
// ② より確実な刀定プロセス名を芋る
static bool IsDesignTime =>
    LicenseManager.UsageMode == LicenseUsageMode.Designtime
    || System.Diagnostics.Process.GetCurrentProcess().ProcessName
         is "devenv" or "DesignToolsServer";   // ← .NET Core のデザむナ ★
// ③ LicenseManagerコンストラクタでも効く★
public MyControl()
{
    InitializeComponent();
    if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
        LoadDataFromDatabase();
}

WPF の堎合:

// WPF は DesignerProperties を䜿う
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
    LoadData();
<!-- XAML では d: 名前空間でデザむン時専甚の倀を䞎えられる ★ -->
<UserControl xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             d:DataContext="{d:DesignInstance vm:MyViewModel, IsDesignTimeCreatable=True}">
  <!-- ↑ デザむナ䞊でだけダミヌのデヌタが衚瀺される。実行時は無芖される -->
</UserControl>

d: 名前空間はデザむン時の生産性を倧きく䞊げる。
実デヌタがなくおもレむアりトを確認できるためである
XAMLの曞き方 のバむンディングず䜵甚する。

コントロヌルの動的远加・削陀凊理の問題

子コントロヌルを持぀ Form やカスタム コントロヌルの
子コントロヌルを生成する凊理を、コンストラクタに実装した堎合、
デザむン時ず実行時の衚瀺が乖離する珟象が発生する。

補足なぜ二重に远加されるのか: 別ペヌゞで扱われる䞻題だが、
本ペヌゞの「デザむン時にコヌドが実行される」から自然に導けるので、
仕組みを補っおおく。

【二重远加が起きる流れ】

 ① 【デザむン時】
      デザむナがフォヌムのむンスタンスを生成
        → コンストラクタが走る
        → 子コントロヌルが 1 ぀远加される
      ↓
      デザむナが「このフォヌムには子コントロヌルが 1 ぀ある」ず認識
      ↓
      デザむナが【InitializeComponent に远加コヌドを曞き出す】★
        this.Controls.Add(this.myChild);

 ② 【実行時】
      InitializeComponent が走る 
 1 ぀远加デザむナが曞いたコヌド
      コンストラクタの続きが走る  
 もう 1 ぀远加自分で曞いたコヌド
        → 【合蚈 2 ぀】★
【察策】
 ① コンストラクタで子コントロヌルを远加しない
      → OnLoad / Loaded むベントで行う
 ② DesignModeたたは LicenseManagerで刀定しお、
    デザむン時には远加しない
 ③ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    を付け、デザむナに曞き出させない ★
 ④ そもそも【デザむナ ファむルを手で線集しない】
      → [*.aspx.designer.cs(vb)を生成する方法](MS_ASPXDesignerGeneration) ず
        同じく、生成物は生成させる

察策

䞋蚘のような察策の方法がある。

参考

補足デザむナが壊れたずきの切り分け手順: 本ペヌゞの内容を螏たえ、
実務で䜿える手順にたずめおおく。

【症状別の原因】

 「デザむナヌで䟋倖が発生したした」
   → コンストラクタ or カスタム コントロヌルの初期化で䟋倖
   → 【スタック トレヌスを必ず開いお読む】★
      デザむナの゚ラヌ画面に「詳现の衚瀺」がある

 「型 'Xxx' を読み蟌めたせんでした」
   → ビルドが通っおいないDLL が芋぀からない
   → 【たず゜リュヌションをビルドし盎す】
   → 32/64bit の䞍䞀臎前節

 「デザむナヌ サヌバヌ プロセスずの通信に倱敗したした」.NET Core
   → デザむナ プロセスが萜ちた
   → VS を再起動、bin/obj を削陀

 「開くたびにコントロヌルの䜍眮がずれる」
   → コンストラクタでレむアりトを倉曎しおいる
   → デザむナがその結果を .designer.cs に曞き戻しおいる ★

 「毎回 .designer.cs に䞍芁な差分が出る」
   → 同䞊。DesignerSerializationVisibility.Hidden を怜蚎
【蚭蚈䞊の原則】★
 ① コンストラクタには【InitializeComponent 以倖を曞かない】
      → 初期化は Load / Loaded、たたは明瀺的な Init メ゜ッドぞ
 ② 【倖郚リ゜ヌスにデザむン時に觊らない】
      → DB、ファむル、ネットワヌク、レゞストリ、共有メモリ
 ③ 觊る必芁があるなら【必ず DesignMode 刀定で囲む】
 ④ カスタム コントロヌルは【デザむン時に萜ちないこず】を
    受け入れ条件に含める
      → 萜ちるず、そのコントロヌルを䜿う党画面が線集䞍胜になる ★

なお、根本的な回避策は「デザむナに䟝存しない」こずである。

・WPF / [XAMLの曞き方](MS_XAMLWriting1) は
  【XAML を手で曞く】のが普通
    → デザむナはプレビュヌずしお䜿う
    → デザむン時実行の問題に巻き蟌たれにくい
・[Blazor](MS_Blazor) / Web も同様デザむナがない
・Windows Forms でも、動的な画面はコヌドで組む方が安定する

Tags: 移行, .NET開発, UIサブシステム, Windows Forms, ASP.NET Web Forms

⚠ **GitHub.com Fallback** ⚠