none
Designer.csでのBindingSourceのISupportInitialize.EndInit()の順番 RRS feed

  • 質問

  • デザイナーでBindingSourceを複数作成してデータバインドでTextBoxとComboBoxに表示しているのですが、
    Designer.csで自動生成される各BindingSourceのISupportInitialize.EndInit()の順番が悪くエラーになってしまいます。

    型 'System.ArgumentException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました
    
    追加情報:DataMember プロパティ 'Inner1' は DataSource に見つかりません。
    ISupportInitialize.EndInit()の順番はデザイナーウインドウでのドキュメントアウトラインと同じなのでどこかでこの順番を指定できないでしょうか。

    BindingSourceを再度指定し直せば一時的に直るのですが、何かの拍子に以下のソースのようになってしまいます。
    メインのコードでは必ず発生するのですが、サンプルコードにするとほとんど発生しないため、原因がわかりません。

    以下エラー時のソースです。

    namespace WindowsFormsApplication1 {
    	public partial class Form1: Form {
    		public Form1() {
    			InitializeComponent();
    
    			MainData = new MainClass();
    			this.bindingSourceMain.DataSource = MainData;
    			this.bindingSourceSub.DataSource = new SubClass();
    		}
    
    		private MainClass MainData;
    
    		public class MainClass {
    			public SubClass.InnerClass[] inner = new SubClass.InnerClass[3]{
    				new SubClass.InnerClass(),
    				new SubClass.InnerClass(),
    				new SubClass.InnerClass(),
    			};
    
    			public SubClass.InnerClass Inner1 { get{return inner[0];} }
    			public SubClass.InnerClass Inner2 { get{return inner[1];} }
    			public SubClass.InnerClass Inner3 { get{return inner[2];} }
    		}
    
    		public class SubClass {
    
    			private List<InnerClass> _InnerList = new List<InnerClass>() {
    				new InnerClass{ id = "1", value ="いち" },
    				new InnerClass{ id = "2", value ="に" },
    				new InnerClass{ id = "3", value ="さん" },
    				new InnerClass{ id = "4", value ="よん" },
    			};
    			public List<InnerClass> InnerList {
    				get {
    					return _InnerList;
    				}
    			}
    
    			private List<InnerClass2> _InnerList2 = new List<InnerClass2>() {
    				new InnerClass2{ id = "2-1", value ="2-いち" },
    				new InnerClass2{ id = "2-2", value ="2-に" },
    				new InnerClass2{ id = "2-3", value ="2-さん" },
    				new InnerClass2{ id = "2-4", value ="2-よん" },
    			};
    			public List<InnerClass2> InnerList2 {
    				get {
    					return _InnerList2;
    				}
    			}
    
    			public class InnerClass {
    				public string id { get; set; }
    				public string value { get; set; }
    			}
    
    			public class InnerClass2 {
    				public string id { get; set; }
    				public string value { get; set; }
    			}
    
    		}
    	}
    }
    
    
    namespace WindowsFormsApplication1 {
    	partial class Form1 {
    		/// <summary>
    		/// 必要なデザイナー変数です。
    		/// </summary>
    		private System.ComponentModel.IContainer components = null;
    
    		/// <summary>
    		/// 使用中のリソースをすべてクリーンアップします。
    		/// </summary>
    		/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    		protected override void Dispose( bool disposing ) {
    			if( disposing && ( components != null ) ) {
    				components.Dispose();
    			}
    			base.Dispose(disposing);
    		}
    
    		#region Windows フォーム デザイナーで生成されたコード
    
    		/// <summary>
    		/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
    		/// コード エディターで変更しないでください。
    		/// </summary>
    		private void InitializeComponent() {
    			this.components = new System.ComponentModel.Container();
    			this.group1 = new System.Windows.Forms.GroupBox();
    			this.combo4 = new System.Windows.Forms.ComboBox();
    			this.innerList2BindingSource3 = new System.Windows.Forms.BindingSource(this.components);
    			this.bindingSourceSub = new System.Windows.Forms.BindingSource(this.components);
    			this.combo3 = new System.Windows.Forms.ComboBox();
    			this.innerList2BindingSource2 = new System.Windows.Forms.BindingSource(this.components);
    			this.combo2 = new System.Windows.Forms.ComboBox();
    			this.innerList2BindingSource1 = new System.Windows.Forms.BindingSource(this.components);
    			this.combo1 = new System.Windows.Forms.ComboBox();
    			this.innerList2BindingSource = new System.Windows.Forms.BindingSource(this.components);
    			this.bindingSourceMain = new System.Windows.Forms.BindingSource(this.components);
    			this.tabControl = new System.Windows.Forms.TabControl();
    			this.page1 = new System.Windows.Forms.TabPage();
    			this.combo11 = new System.Windows.Forms.ComboBox();
    			this.innerListBindingSource1 = new System.Windows.Forms.BindingSource(this.components);
    			this.combo10 = new System.Windows.Forms.ComboBox();
    			this.innerListBindingSource = new System.Windows.Forms.BindingSource(this.components);
    			this.text0 = new System.Windows.Forms.TextBox();
    			this.text1 = new System.Windows.Forms.TextBox();
    			this.group1.SuspendLayout();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource3)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.bindingSourceSub)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource2)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource1)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.bindingSourceMain)).BeginInit();
    			this.tabControl.SuspendLayout();
    			this.page1.SuspendLayout();
    			((System.ComponentModel.ISupportInitialize)(this.innerListBindingSource1)).BeginInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerListBindingSource)).BeginInit();
    			this.SuspendLayout();
    			// 
    			// group1
    			// 
    			this.group1.Controls.Add(this.combo4);
    			this.group1.Controls.Add(this.combo3);
    			this.group1.Controls.Add(this.combo2);
    			this.group1.Controls.Add(this.combo1);
    			this.group1.Location = new System.Drawing.Point(12, 12);
    			this.group1.Name = "group1";
    			this.group1.Size = new System.Drawing.Size(163, 172);
    			this.group1.TabIndex = 35;
    			this.group1.TabStop = false;
    			this.group1.Text = "group";
    			// 
    			// combo4
    			// 
    			this.combo4.DataSource = this.innerList2BindingSource3;
    			this.combo4.DisplayMember = "value";
    			this.combo4.DropDownHeight = 200;
    			this.combo4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
    			this.combo4.DropDownWidth = 100;
    			this.combo4.FormattingEnabled = true;
    			this.combo4.ImeMode = System.Windows.Forms.ImeMode.Off;
    			this.combo4.IntegralHeight = false;
    			this.combo4.Location = new System.Drawing.Point(17, 90);
    			this.combo4.Name = "combo4";
    			this.combo4.Size = new System.Drawing.Size(100, 20);
    			this.combo4.TabIndex = 18;
    			this.combo4.ValueMember = "id";
    			// 
    			// innerList2BindingSource3
    			// 
    			this.innerList2BindingSource3.DataMember = "InnerList2";
    			this.innerList2BindingSource3.DataSource = this.bindingSourceSub;
    			// 
    			// bindingSourceSub
    			// 
    			this.bindingSourceSub.DataSource = typeof(WindowsFormsApplication1.Form1.SubClass);
    			// 
    			// combo3
    			// 
    			this.combo3.DataSource = this.innerList2BindingSource2;
    			this.combo3.DisplayMember = "value";
    			this.combo3.DropDownHeight = 200;
    			this.combo3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
    			this.combo3.DropDownWidth = 100;
    			this.combo3.FormattingEnabled = true;
    			this.combo3.ImeMode = System.Windows.Forms.ImeMode.Off;
    			this.combo3.IntegralHeight = false;
    			this.combo3.Location = new System.Drawing.Point(17, 66);
    			this.combo3.Name = "combo3";
    			this.combo3.Size = new System.Drawing.Size(100, 20);
    			this.combo3.TabIndex = 15;
    			this.combo3.ValueMember = "id";
    			// 
    			// innerList2BindingSource2
    			// 
    			this.innerList2BindingSource2.DataMember = "InnerList2";
    			this.innerList2BindingSource2.DataSource = this.bindingSourceSub;
    			// 
    			// combo2
    			// 
    			this.combo2.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
    			this.combo2.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
    			this.combo2.DataSource = this.innerList2BindingSource1;
    			this.combo2.DisplayMember = "value";
    			this.combo2.DropDownHeight = 200;
    			this.combo2.DropDownWidth = 100;
    			this.combo2.FormattingEnabled = true;
    			this.combo2.ImeMode = System.Windows.Forms.ImeMode.Off;
    			this.combo2.IntegralHeight = false;
    			this.combo2.Location = new System.Drawing.Point(17, 42);
    			this.combo2.MaxLength = 20;
    			this.combo2.Name = "combo2";
    			this.combo2.Size = new System.Drawing.Size(100, 20);
    			this.combo2.TabIndex = 10;
    			this.combo2.ValueMember = "id";
    			// 
    			// innerList2BindingSource1
    			// 
    			this.innerList2BindingSource1.DataMember = "InnerList2";
    			this.innerList2BindingSource1.DataSource = this.bindingSourceSub;
    			// 
    			// combo1
    			// 
    			this.combo1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
    			this.combo1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
    			this.combo1.DataSource = this.innerList2BindingSource;
    			this.combo1.DisplayMember = "value";
    			this.combo1.DropDownHeight = 200;
    			this.combo1.DropDownWidth = 100;
    			this.combo1.FormattingEnabled = true;
    			this.combo1.ImeMode = System.Windows.Forms.ImeMode.Off;
    			this.combo1.IntegralHeight = false;
    			this.combo1.Location = new System.Drawing.Point(17, 18);
    			this.combo1.MaxLength = 20;
    			this.combo1.Name = "combo1";
    			this.combo1.Size = new System.Drawing.Size(100, 20);
    			this.combo1.TabIndex = 8;
    			this.combo1.ValueMember = "id";
    			// 
    			// innerList2BindingSource
    			// 
    			this.innerList2BindingSource.DataMember = "InnerList2";
    			this.innerList2BindingSource.DataSource = this.bindingSourceSub;
    			// 
    			// bindingSourceMain
    			// 
    			this.bindingSourceMain.DataSource = typeof(WindowsFormsApplication1.Form1.MainClass);
    			// 
    			// tabControl
    			// 
    			this.tabControl.Controls.Add(this.page1);
    			this.tabControl.ItemSize = new System.Drawing.Size(80, 18);
    			this.tabControl.Location = new System.Drawing.Point(8, 206);
    			this.tabControl.Name = "tabControl";
    			this.tabControl.SelectedIndex = 0;
    			this.tabControl.Size = new System.Drawing.Size(262, 161);
    			this.tabControl.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
    			this.tabControl.TabIndex = 36;
    			// 
    			// page1
    			// 
    			this.page1.Controls.Add(this.combo11);
    			this.page1.Controls.Add(this.combo10);
    			this.page1.Controls.Add(this.text0);
    			this.page1.Controls.Add(this.text1);
    			this.page1.Location = new System.Drawing.Point(4, 22);
    			this.page1.Name = "page1";
    			this.page1.Padding = new System.Windows.Forms.Padding(3);
    			this.page1.Size = new System.Drawing.Size(254, 135);
    			this.page1.TabIndex = 0;
    			this.page1.Text = "tab";
    			this.page1.UseVisualStyleBackColor = true;
    			// 
    			// combo11
    			// 
    			this.combo11.DataSource = this.innerListBindingSource1;
    			this.combo11.DisplayMember = "value";
    			this.combo11.DropDownHeight = 240;
    			this.combo11.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
    			this.combo11.FormattingEnabled = true;
    			this.combo11.IntegralHeight = false;
    			this.combo11.Location = new System.Drawing.Point(123, 31);
    			this.combo11.Name = "combo11";
    			this.combo11.Size = new System.Drawing.Size(100, 20);
    			this.combo11.TabIndex = 18;
    			this.combo11.ValueMember = "id";
    			// 
    			// innerListBindingSource1
    			// 
    			this.innerListBindingSource1.DataMember = "InnerList";
    			this.innerListBindingSource1.DataSource = this.bindingSourceSub;
    			// 
    			// combo10
    			// 
    			this.combo10.DataSource = this.innerListBindingSource;
    			this.combo10.DisplayMember = "value";
    			this.combo10.DropDownHeight = 240;
    			this.combo10.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
    			this.combo10.FormattingEnabled = true;
    			this.combo10.IntegralHeight = false;
    			this.combo10.Location = new System.Drawing.Point(17, 31);
    			this.combo10.Name = "combo10";
    			this.combo10.Size = new System.Drawing.Size(100, 20);
    			this.combo10.TabIndex = 17;
    			this.combo10.ValueMember = "id";
    			// 
    			// innerListBindingSource
    			// 
    			this.innerListBindingSource.DataMember = "InnerList";
    			this.innerListBindingSource.DataSource = this.bindingSourceSub;
    			// 
    			// text0
    			// 
    			this.text0.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bindingSourceMain, "Inner1.value", true));
    			this.text0.ImeMode = System.Windows.Forms.ImeMode.On;
    			this.text0.Location = new System.Drawing.Point(17, 57);
    			this.text0.MaxLength = 20;
    			this.text0.Name = "text0";
    			this.text0.Size = new System.Drawing.Size(100, 19);
    			this.text0.TabIndex = 28;
    			this.text0.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
    			// 
    			// text1
    			// 
    			this.text1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bindingSourceMain, "Inner2.value", true));
    			this.text1.ImeMode = System.Windows.Forms.ImeMode.On;
    			this.text1.Location = new System.Drawing.Point(123, 57);
    			this.text1.MaxLength = 20;
    			this.text1.Name = "text1";
    			this.text1.Size = new System.Drawing.Size(100, 19);
    			this.text1.TabIndex = 29;
    			this.text1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
    			// 
    			// Form1
    			// 
    			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
    			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    			this.ClientSize = new System.Drawing.Size(317, 386);
    			this.Controls.Add(this.group1);
    			this.Controls.Add(this.tabControl);
    			this.Name = "Form1";
    			this.Text = "Form1";
    			this.group1.ResumeLayout(false);
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource3)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.bindingSourceSub)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource2)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource1)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerList2BindingSource)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.bindingSourceMain)).EndInit();
    			this.tabControl.ResumeLayout(false);
    			this.page1.ResumeLayout(false);
    			this.page1.PerformLayout();
    			((System.ComponentModel.ISupportInitialize)(this.innerListBindingSource1)).EndInit();
    			((System.ComponentModel.ISupportInitialize)(this.innerListBindingSource)).EndInit();
    			this.ResumeLayout(false);
    
    		}
    
    		#endregion
    
    		private System.Windows.Forms.GroupBox group1;
    		private System.Windows.Forms.ComboBox combo4;
    		private System.Windows.Forms.ComboBox combo3;
    		private System.Windows.Forms.ComboBox combo2;
    		private System.Windows.Forms.ComboBox combo1;
    		private System.Windows.Forms.TabControl tabControl;
    		private System.Windows.Forms.TabPage page1;
    		private System.Windows.Forms.ComboBox combo11;
    		private System.Windows.Forms.ComboBox combo10;
    		private System.Windows.Forms.BindingSource bindingSourceSub;
    		private System.Windows.Forms.BindingSource bindingSourceMain;
    		private System.Windows.Forms.TextBox text0;
    		private System.Windows.Forms.TextBox text1;
    		private System.Windows.Forms.BindingSource innerList2BindingSource3;
    		private System.Windows.Forms.BindingSource innerList2BindingSource2;
    		private System.Windows.Forms.BindingSource innerList2BindingSource1;
    		private System.Windows.Forms.BindingSource innerList2BindingSource;
    		private System.Windows.Forms.BindingSource innerListBindingSource1;
    		private System.Windows.Forms.BindingSource innerListBindingSource;
    	}
    }



    2015年5月18日 10:38

回答

  • エラーになるのは、

    this.text0.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bindingSourceMain, "Inner1.value", true));

    の部分でしょうか?

    この場合、bindingSourceMainのDataSourceの設定がInitializeComponentメソッドの実行後ですので、エラーになるような気がします。
    デザイナーで指定する部分とコードで指定する部分が混在するとわかりにくくなりますし、設定もしずらい面があると思いますので、バインディングの部分は全てコードで指定されてみてはいかがでしょうか?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kitunechan 2015年5月19日 7:06
    2015年5月18日 11:22
    モデレータ

すべての返信

  • エラーになるのは、

    this.text0.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bindingSourceMain, "Inner1.value", true));

    の部分でしょうか?

    この場合、bindingSourceMainのDataSourceの設定がInitializeComponentメソッドの実行後ですので、エラーになるような気がします。
    デザイナーで指定する部分とコードで指定する部分が混在するとわかりにくくなりますし、設定もしずらい面があると思いますので、バインディングの部分は全てコードで指定されてみてはいかがでしょうか?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kitunechan 2015年5月19日 7:06
    2015年5月18日 11:22
    モデレータ
  • 実際にエラー箇所として表示されるのは
    ( (System.ComponentModel.ISupportInitialize)( this.bindingSourceSub ) ).EndInit();
    になります。

    VisualStudioのデータソースウインドウからドラッグ&ドロップでTextBoxに設定できるので便利だったのですが、エラーの原因のなる部分は別で指定してみます。


    2015年5月19日 2:03
  • こんにちは。

    おそらく他の依存しているBindingSourceがEndInitされる前に、bindingSourceSubがEndInitされてしまうためですよね…。
    デザイナで自動生成されるInitializeComponentの順序を制御する方法があるなら私も興味ありますが、
    順序に依存する部分はここで実行しないほうが良い気もします。

    コードからInitializeComponentを変更してもデザイナに変更が入った場合にまた並び替えられてしまうような気もしますし。

    trapemiyaさんが仰っているようにバインディングの部分はコード側で定義したほうが良いのかなと。

    2015年5月19日 2:26
    モデレータ
  • ちなみにvisual studio2013 Proを使用しています
    BindingSourceの順序は固定されないようですね
    見た目的にも好きな順序にしたいと思うのですが

    再度完全なコードを置いておきます。
    Form1.cs http://ideone.com/T0A6JT
    Form1.Designer.cs http://ideone.com/NlPDB1
    各バインドを設定した時は1枚目の画像の順になるのですが、いったんForm1をすべて閉じてから再度デザインを開くと2枚目のようになってしまうようです。
    2枚目のようになってしまった後にDesigner.csが更新されるとEndInitが並び替えられてしまいエラーになります。


    2015年5月19日 3:04
  • 掲載されたコードを私の方でも試してみましたが、再現しました。
    基本的にISupportInitializeのメソッドを自動生成する部分であり、他との依存性を考慮してコード生成するのは個人的には酷なような気がします。先にも書いた通り、不具合というよりは仕様の範囲内で、このような部分はコードで明に記述するしかないのかな?と個人的には思います。残念ですが、現時点でVisual Studioにコード生成のこれ以上の仕様を求めるのは厳しいように思います。
    ネットで検索してみましてが、私の探し方が悪いのかもしれませんが、このような現象で困っている記述を見つけることができませんでした。これも、上述した意見の理由の一つで、Visual Studioにとって、需要の割にはコード自動生成開発のコストが高いように思えました。

    #ただ、何らかの仕組みで、生成オーダーを人間が制御する仕組みがあっても良いのかな~と思ったりはします。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2015年5月19日 6:26
    モデレータ
  • 試していただきありがとうございます。
    再現しているのでそういう仕様ということで割り切りたいと思います。

    ありがとうございました。

    2015年5月19日 7:05