2016-08-28 26 views
2

にデータバインドされたDataGridViewかのBindingSourceを投げ、私は私のプロジェクトは、このリンク上でモデル化され、C#のWinformsとEntity Frameworkのに働いています:Databinding with WinFormsC#Winフォーム(Entity Frameworkの) - のDataTable

私の質問は、私はDataGridViewかを変換することができる方法でありますBindingSource~DataTable

私はこのコードを試みた:

DataTable data = (DataTable)(DataGridView1.DataSource); 

をそれがエラーで失敗しました:

Unable to cast object of type 'System.Windows.Forms.BindingSource' to type 'System.Data.DataTable'.

そして私の代わりにこのコードを試みた:

BindingSource bs = (BindingSource)DataGridView1.DataSource; 
DataTable dt = (DataTable)bs.DataSource; 

これはで終わります別のエラー:

Unable to cast object of type 'System.Data.Entity.Internal.DbLocalView`1[Project1.Contexts.table1]' to type 'System.Data.DataTable'.

他の類似した質問や他のサイトを検索しようとしましたが、System.Data.Entity.Internal.DbLocalViewDataTableに変換する方法が見つかりませんでした。

編集:

ここに私のコードとの要件があります。

要件:

私は2つの形態があり、第一のフォームがenrollmedsBindingSourceにDataBounded enrollmedsDataGridViewという名前DataGridViewを持っています。 enrollmedsBindingSource.DataSourcem3d.enrollmeds.Localm3dは私の状況です)に設定されています。ウィンドウには(選択されたアイテムにつき備考)のテキストボックス、Saveのボタンとリストを保存するAddのボタンがあり、アイテムマスターリストのアイテムの選択のための2番目のフォームが開きます。

が第一形態への第二のフォームで選択した項目を転送するには、私は DataGridView DataTableに、その後第一形式との BindingSourceをクリアキャスト私が欲しいもの BindingSource

に選択した項目を持つようにされて再追加

:第2回フォームのための方法はすでにデフォルトで選択項目を設定することができるように選択されるものを項目を知っている第一のフォームのための

コード(EnrollMedicationFrm)(現在は第二のフォームのデフォルトは、すべての項目がチェックされています) 210第二フォーム(EnrollMedSelectionFrm)ため

1st Form - EnrollMedicationFrm

M3dEntities m3d = new M3dEntities(); 
    enrollmeds _enrollmeds; 
    EnrollMedSelectionFrm enrollselectfrm; 
    public DataTable SelectedItems { get; set; } 
    public string SelectedAdmNo { get; set; } 

    private void EnrollMedicationFrm_Load(object sender, EventArgs e) 
    { 
     var _SelectedPKAdm = (from p in m3d.admission 
           where p.admissionNo == SelectedAdmNo 
           select p.PK_Admission).FirstOrDefault(); 

     int _selectedAdmno = int.Parse(SelectedAdmNo); 
     m3d.enrollmeds.Where(adm => adm.FK_Admission == _SelectedPKAdm).ToList(); 
     this.enrollmedsBindingSource.DataSource = m3d.enrollmeds.Local; 
    } 


    private void AddBtn_Click(object sender, EventArgs e) 
    { 
     enrollselectfrm = new EnrollMedSelectionFrm(); 

     var pxdetails = (from adm in m3d.admission 
         join pxDC in m3d.datacenter 
         on adm.FK_DC_Patient equals pxDC.PK_Datacenter 
         where adm.admissionNo == SelectedAdmNo 
         select new 
         { 
          adm, 
          pxDC 
         }).FirstOrDefault(); 

     if (enrollselectfrm.ShowDialog() == DialogResult.OK) 
     { 
      if (SelectedItems == null) 
      { 
       enrollmedsBindingSource.Clear(); 
      } 
      else 
      { 
       enrollmedsBindingSource.Clear(); 

       foreach (DataRow dr in SelectedItems.Rows) 
       { 
        _enrollmeds = new enrollmeds(); 

        _enrollmeds.FK_DC_Patient = pxdetails.pxDC.PK_Datacenter; 
        _enrollmeds.FK_DC_userAdd = mainfrm.PK_DC_UserLoggedIn; 
        var svrDT = ((IObjectContextAdapter)m3d).ObjectContext.CreateQuery<DateTime>("CurrentDateTime() "); 
        DateTime currdatetime = svrDT.AsEnumerable().First(); 
        _enrollmeds.AddDateTime = currdatetime; 
        _enrollmeds.FK_Admission = pxdetails.adm.PK_Admission; 
        _enrollmeds.Qty = 0; 

        int pkItems = int.Parse(dr.Field<string>("PK_Items").ToString()); 
        var itemdtls = (from i in m3d.items 
            where i.PK_Items == pkItems 
            select i).FirstOrDefault(); 

        _enrollmeds.FK_Items = pkItems; 
        _enrollmeds.ItemRemarks = itemdtls.ItemRemarks; 

        enrollmedsBindingSource.Add(_enrollmeds); 
       } 
      } 
     } 
    } 

コード:

2nd Form - EnrollMedSelectionFrm

M3dEntities m3d = new M3dEntities(); 
    private void EnrollMedSelectionFrm_Load(object sender, EventArgs e) 
    { 
     var items = from i in m3d.items 
        where i.ItemGroup == "Medicine" 
        select new 
        { 
         i.PK_Items, 
         i.ItemID, 
         i.ItemDesc, 
         i.GenericName 
        }; 

     if (items != null) 
     { 
      DataTable dt = new DataTable(); 
      foreach (DataGridViewColumn col in ItemSelectionDataGridView.Columns) 
      { 
       dt.Columns.Add(col.Name); 
       col.DataPropertyName = col.Name; 
      }; 
      foreach (var element in items) 
      { 
       var row = dt.NewRow(); 
       row["PK_Items"] = element.PK_Items; 
       row["ItemID"] = element.ItemID; 
       row["ItemDesc"] = element.ItemDesc; 
       row["GenericName"] = element.GenericName; 
       dt.Rows.Add(row); 
      } 
      ItemSelectionDataGridView.DataSource = dt; 
     } 
    } 

    private void SelectBtn_Click(object sender, EventArgs e) 
    { 
     EnrollMedicationFrm enrollfrm = (EnrollMedicationFrm)Application.OpenForms["EnrollMedicationFrm"]; 
     DataTable dt = new DataTable(); 
     dt = (DataTable)ItemSelectionDataGridView.DataSource; 
     DataRow[] result = dt.Select("SelectedChkBox = 1"); 

     if (result.Count() < 1) 
     { 
      enrollfrm.SelectedItems = null; 
     } 
     else 
     { 
      enrollfrm.SelectedItems = result.CopyToDataTable(); 
     } 

     this.DialogResult = DialogResult.OK; 
    } 

私はこの流れに多くのフォームの検証を持っていますが、それらのすべては、この問題を持って:(一度 この問題は修正されています。それらのすべてまたはほとんどを修正することもできます。

私はこの問題を解決する方法、他のアプローチや回避策にも大きな助けになるかもしれません。大いに助けてください:)

+0

_DataGridView1_で設定されているデータソースタイプは何ですか? – Jackdaw

+0

エンティティフレームワークのバインディングソースtable1 @Jackdaw – Henry

+1

'DataGridView'は**ビジュアル**コンポーネントです。データだけではなく** ** DataTableにキャストすることはできません(これは**データのみです**)。 'BindingSource'と同じです - これは視覚的ではないコンポーネントですが、もう一度**素人データだけでなく** DataTableにキャストすることはできません。あなたがする必要があるのは、グリッドやバインディングソースのために**基になるデータ**を使用し、それを 'DataTable'にキャスト/変換することです - あるいはグリッドやバインディングソースを最初に送り出すために' DataTable'を使います! –

答えて

1

DataTableを使用する必要はありません。代わりに、List<T>DbSet<T>ObservableCollection<T>BindingList<T>などのクラスに依存する必要があります。現在の要件に

レッツ・フォーカス:

What I want is to have a way for the 2nd form to know what items are already selected...

これらの注意事項を考慮してください。

  • あなたはList<T>DataGridViewをバインドすると、各行のDataBoundItemプロパティがタイプTです。

  • あなたはいくつかの行をチェックするDataGridViewを使用しているので、あなたは、単にグリッドのチェックボックス列を持っているし、その名前を設定することができCast<DataGridViewRow>

を呼び出すことにより、DataGridViewRowsコレクションを検索することができますたとえばCheckBoxColumn1になります。次に、あなたの選択ボタンで、あなたはこのようチェックされた項目を見つけることができます:上記のコードで

private void selectButton_Click(object sender, EventArgs e) 
{ 
    this.dataGridView1.EndEdit(); 
    var checkedItems = this.dataGridView1.Rows.Cast<DataGridViewRow>() 
          .Where(x => (bool?)x.Cells["CheckBoxColumn1"].Value == true) 
          .Select(x => x.DataBoundItem) 
          .Cast<MyItem>().ToList(); 

    //use checkedItems 
} 

を私はMyItemはあなたがグリッドに表示されているリスト項目のタイプであるはず。

+0

答えには、 'DataTable'の使用を避け、型付きリストを使い続けるために必要な情報が含まれているようです。あなたは答えについての質問がある場合私に教えてください:) –

+0

こんにちは@RezaAghaei、遅い応答に申し訳ありません。 2番目のフォームに 'DataGridView'を追加して答えを試し、データソースを' checkedItems'に設定すると、1番目のフォームのみのすべての項目が表示されます:)。答えは、他のフォームがどの項目が選択されているかを知るための問題を解決します。しかし、私はもう1つの懸念があります。なぜなら、1番目のフォームは 'Qty'と' ItemRemarks'フィールドを持っているからです。私は最初のフォームで項目を削除する(2番目のフォームでチェックを外した)方法を理解していないし、QtyとItemRemarksの編集を保持している。これを別の質問として投稿する必要がありますか、それとも私の現在の質問に含めることができますか?非常にありがとう – Henry

+0

あなたの質問を私の理解に基づいて、私はあなたの最初のフォームのデータソースとしてチェック項目を設定すべきではないと思う、あなたは何とかそれらを使用する必要があります。 –

関連する問題