C# Winform( Entity Framework )- 将数据绑定(bind) DataGridView 或 BindingSource 转换为 DataTable

标签 c# winforms entity-framework datagridview datatable

我正在使用 C# Winforms 和 Entity Framework,我的项目是基于此链接建模的:Databinding with WinForms

我的问题是如何将 DataGridViewBindingSource 转换为 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.DbLocalView 转换为 DataTable 的方法。

编辑:

这是我的代码和要求。

要求:

我有 2 个表单,第一个表单有名为 enrollmedsDataGridViewDataGridView,它的数据绑定(bind)到 enrollmedsBindingSourceenrollmedsBindingSource.DataSource 设置为 m3d.enrollmeds.Local(m3d 是我的上下文)。窗口有用于 ItemRemarks 的文本框(每个选定项目的备注)、用于保存列表的用于 Save 的按钮和用于用于打开 Add 的按钮在 Item Masterlist 中选择项目的第二种形式。

为了将第二个表单上的选定项目转移到第一个表单,我将 DataGridView 转换为 DataTable 然后清除第一个表单的 BindingSource并将选择的项目重新添加到 BindingSource

我想要的是让第二个表单知道已经选择了哪些项目以便能够设置默认选择的项目(目前第二个表单默认是所有项目都未选中)

第一种形式的代码 (EnrollMedicationFrm):

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

第 2 表格的代码 (EnrollMedSelectionFrm):

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

我在这个流程中有很多表单验证,但它们都有这个问题:( 一旦这个问题得到解决,我认为所有或大部分问题也可以得到解决

请指导我如何解决这个问题,其他方法甚至变通方法可能会有很大帮助,在此先感谢您:)

最佳答案

使用 Entity Framework 时,您不需要使用 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...

考虑这些注意事项:

  • 当你绑定(bind)一个 DataGridViewList<T> , DataBoundItem每行的属性类型为 T .

  • 您可以搜索 Rows收藏DataGridView调用 Cast<DataGridViewRow>

由于您使用的是 DataGridView要检查某些行,您只需在网格中添加一个复选框列并将其名称设置为 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是您在网格中显示的列表项类型。

关于C# Winform( Entity Framework )- 将数据绑定(bind) DataGridView 或 BindingSource 转换为 DataTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39191624/

相关文章:

c# - Entity Framework 4.0 - 版本控制

c# - 尝试使用 Excel 2007 进行办公自动化,但一直使用 Excel 2003

c# - 如何为这个 if 语句使用三元?

c# - 使用跟踪监听器重定向所有调试输出

c# - 全局变量和局部变量澄清

c# - 应该如何在 WinForms GUI 控件和客户端类之间同步数据?

c# - Entity Framework EF.Functions.Like 与 string.Contains

c# - SQL 查询在代码中超时,但在管理工作室中需要几秒钟

c# - CompareTo 的问题

c# - 在 C# 中如何动态指定对象的成员,如 obj ["abc"] 在 PHP 中