【问题标题】:C# Winform (Entity Framework) - cast databound DataGridView or BindingSource to DataTableC# Winform(实体框架) - 将数据绑定 DataGridView 或 BindingSource 转换为 DataTable
【发布时间】:2016-08-28 13:11:38
【问题描述】:

我正在使用 C# Winforms 和实体框架,我的项目基于此链接:Databinding with WinForms

我的问题是如何将DataGridViewBindingSource 转换为DataTable

我试过这段代码:

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

但失败并出现错误:

无法将“System.Windows.Forms.BindingSource”类型的对象转换为“System.Data.DataTable”类型。

然后我尝试了以下代码:

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

但这会导致另一个错误:

无法将“System.Data.Entity.Internal.DbLocalView`1[Project1.Contexts.table1]”类型的对象转换为“System.Data.DataTable”类型。

尝试在其他网站上搜索其他类似问题,但找不到将System.Data.Entity.Internal.DbLocalView 转换为DataTable 的方法。

编辑:

这是我的代码和要求。

要求:

我有 2 个表单,第一个表单有 DataGridView,名为 enrollmedsDataGridView,其 DataBounded 为 enrollmedsBindingSourceenrollmedsBindingSource.DataSource 设置为 m3d.enrollmeds.Localm3d 是我的上下文)。窗口有ItemRemarks 的文本框(每个选定项目的备注),Save 的按钮用于保存列表,Add 的按钮将打开第二个表单以选择项目主列表中的项目。

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

我想要的是让第二种形式知道哪些项目已经被选中,以便能够设置默认选择的项目(目前第二种形式默认是所有项目都未选中)

第一种形式的代码 (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);
                }
            }
        }
    }

第二种形式的代码 (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;
    }

我对这个流程进行了许多表单验证,但它们都有这个问题:( 一旦这个问题得到解决,我认为所有或大部分都可以解决

请指导我如何解决这个问题,其他方法甚至解决方法可能会有很大帮助,非常感谢提前:)

【问题讨论】:

  • DataGridView1中设置的数据源类型是什么?
  • 实体框架table1的Bindingsource @Jackdaw
  • A DataGridView 是一个 visual 组件 - 不仅仅是数据 - 所以 cannot 可能被转换为 DataTable(其中仅数据)。 BindingSource 也是如此 - 这是一个非可视组件,但同样:它比裸数据更多,因此您不能将其转换为 DataTable。您需要做的是使用网格或绑定源的基础数据并将其转换/转换为DataTable - 或使用DataTable 在第一个提供网格或绑定源地点!
  • 嗨@mar​​c_s,我认为我的问题的基础数据System.Data.Entity.Internal.DbLocalView。但我找不到将DbLocalView 转换为DataTable 的方法。你能给我一个关于如何进行转换的示例或链接吗?
  • 如果您已经创建了DataTable,那么只需将行添加到DataTable。如果您没有DataTable,请查看此post。但我很好奇您在使用 Entity Framewrok 时考虑到 DataTable 的实际要求。

标签: c# winforms entity-framework datagridview datatable


【解决方案1】:

使用实体框架时,您不需要使用DataTable。相反,您应该依赖 List&lt;T&gt;DbSet&lt;T&gt;ObservableCollection&lt;T&gt;BindingList&lt;T&gt; 等类。

让我们关注当前的需求:

我想要的是让第二种形式知道什么是物品 已经选择...

请考虑以下注意事项:

  • 当您将DataGridView 绑定到List&lt;T&gt; 时,每行的DataBoundItem 属性的类型为T

  • 您可以通过调用Cast&lt;DataGridViewRow&gt; 来搜索RowsDataGridView 集合

由于您使用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 是您在网格中显示的列表项的类型。

【讨论】:

  • 似乎答案包含您需要避免使用DataTable 并继续使用类型列表的信息。如果您对答案有任何疑问,请告诉我:)
  • 嗨@RezaAghaei,抱歉回复晚了。通过在第二种形式中添加一些DataGridView 来尝试您的答案,然后将数据源设置为checkedItems,它仅显示第一种形式中的所有项目:)。答案解决了另一个表单知道如何选择哪些项目的问题。但是我还有另一个问题,因为第一种形式有 QtyItemRemarks 字段。我不知道如何在第一个表单上删除项目(在第二个表单上未选中)并保留对 Qty 和 ItemRemarks 的编辑。我需要将此作为另一个问题发布还是可以成为我当前问题的一部分?非常感谢
  • 根据我对你的问题的理解,我认为你不应该将选中的项目设置为你的第一个表单的数据源,你应该以某种方式使用它们。
  • 我不知道那些被检查的项目有什么用,你知道的更好。例如,您可以使用它们将它们添加到List。您可以将它们用作过滤器和...。但我可以猜测直接将它们用作您的第一个网格的数据源可能是不正确的。似乎第一个网格显示了两个实体之间的1-N 关系,该关系的一个分支是那些选中的项目。
  • 与我们找到已检查项目的方式相同,我们也可以找到未检查项目并使用它们。您可以返回两个 List,包含选中和未选中的项目,并应用您需要对它们执行的任何操作。
猜你喜欢
  • 2012-01-07
  • 1970-01-01
  • 2011-12-05
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2021-09-15
  • 2015-07-04
相关资源
最近更新 更多