C# Winform (Entity Framework) - cast databound DataGridView or BindingSource to DataTable

风流意气都作罢 提交于 2020-01-01 07:05:07

问题


I am working with C# Winforms and Entity Framework, my project is modeled on this link: Databinding with WinForms

My question is how can I convert a DataGridView or a BindingSource to a DataTable?

I tried this code:

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

but that failed with an error:

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

Then I tried the this code instead:

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

but this ends up with another error:

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

Tried to search other similar questions and on other sites but cannot found a way to convert System.Data.Entity.Internal.DbLocalView to DataTable.

Edit:

Here's my code and requirements.

Requirements:

I have 2 forms, 1st form has DataGridView named enrollmedsDataGridView which DataBounded to enrollmedsBindingSource. enrollmedsBindingSource.DataSource is set to m3d.enrollmeds.Local (m3d is my context). Window has textbox for the ItemRemarks(remarks per item selected), a button for Save to save the list and button for Add which will open the 2nd form for the selection of items on the Item Masterlist.

To transfer the selected items on the 2nd form to 1st form, I cast the DataGridView to DataTable then clear the BindingSource of 1st form and Re-Add the items selected to BindingSource

What I want is to have a way for the 2nd form to know what items are already selected to be able to set the items selected by default (currently 2nd form default is all items are unchecked)

Codes for 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);
                }
            }
        }
    }

Codes for 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;
    }

I have many form validations with this flow, but all of them has this issue :( Once this issue is fixed i think all or most of them can be fixed too

Please guide me on how to solve this problem, other approach or even a workaround could be a great help, Thanks very much in advance :)


回答1:


When using Entity Framework you don't need to use DataTable. Instead you should rely on classes like List<T>, DbSet<T>, ObservableCollection<T>, BindingList<T> and so on.

Let's focus on current requirement:

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

Consider these notes:

  • When you bind a DataGridView to a List<T>, the DataBoundItem property of each row is of type T.

  • You can search on a Rows collection of DataGridView by calling Cast<DataGridViewRow>

Since you are using a DataGridView to check some rows, you can simply have a check-box column in grid and set its name to CheckBoxColumn1 for example. Then in your select button, you can find checked items this way:

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 
}

In above code I supposed MyItem is type of list items which you are showing in grid.



来源:https://stackoverflow.com/questions/39191624/c-sharp-winform-entity-framework-cast-databound-datagridview-or-bindingsourc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!