C#Winform(实体框架) - 将数据绑定DataGridView或BindingSource转换为DataTable [英] C# Winform (Entity Framework) - cast databound DataGridView or BindingSource to DataTable
问题描述
我正在使用C#Winforms和Entity Framework,我的项目是建立在这个链接上的:
M3dEn tities m3d = new M3dEntities();
enrollmeds _enrollmeds;
EnrollMedSelectionFrm enrollselectfrm;
public DataTable SelectedItems {get;组; }
public string SelectedAdmNo {get;组; }
private void EnrollMedicationFrm_Load(object sender,EventArgs e)
{
var _SelectedPKAdm =(from p in m3d.admission
其中p.admissionNo == SelectedAdmNo
选择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
选择新
{
adm,
pxDC
})。FirstOrDefault();
if(enrollselectfrm.ShowDialog()== DialogResult.OK)
{
if(SelectedItems == null)
{
enrollmedsBindingSource.Clear );
}
else
{
enrollmedsBindingSource.Clear();
foreach(SelectedItems.Rows中的DataRow dr)
{
_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 =(从我在m3d.items
其中i.PK_Items == pkItems
选择i).FirstOrDefault();
_enrollmeds.FK_Items = pkItems;
_enrollmeds.ItemRemarks = itemdtls.ItemRemarks;
enrollmedsBindingSource.Add(_enrollmeds);
}
}
}
}
em>第二个表格的代码 (EnrollMedSelectionFrm)
:
M3dEntities m3d = new M3dEntities();
private void EnrollMedSelectionFrm_Load(object sender,EventArgs e)
{
var items =从我在m3d.items
其中i.ItemGroup ==Medicine
select新
{
i.PK_Items,
i.ItemID,
i.ItemDesc,
i.GenericName
};
if(items!= null)
{
DataTable dt = new DataTable();
foreach(ItemSelectionDataGridView.Columns中的DataGridViewColumn col)
{
dt.Columns.Add(col.Name);
col.DataPropertyName = col.Name;
};
foreach(项目中的var元素)
{
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;
}
我有这个流程的许多表单验证,但都有这个问题(
一旦这个问题解决了,我认为所有或大部分都可以修复
请指导我如何解决这个问题,其他方法或即使是一个解决方法可能是一个很大的帮助,非常感谢提前:)
使用实体框架时,您不需要使用 DataTable
。相反,您应该依赖类,例如 List< T>
, DbSet< T>
, ObservableCollection ; T>
, BindingList< T>
等等。
目前的要求:
我想要的是让第二种形式知道哪些项目是
已经选择的方法
请考虑以下注意事项:
-
当您将
DataGridView
绑定到列表< T>
时,DataBoundItem
每个行的属性类型为T
。 -
您可以搜索通过调用 集合
DataGridView
us / library / bb341406(v = vs.110).aspxrel =nofollow>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)
。选择(x => x.DataBoundItem)
.Cast< MyItem>()。ToList();
//使用checkedItems
}
在上面的代码中假设 MyItem
是您在网格中显示的列表项的类型。
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 :)
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 aList<T>
, theDataBoundItem
property of each row is of typeT
.You can search on a
Rows
collection ofDataGridView
by callingCast<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.
这篇关于C#Winform(实体框架) - 将数据绑定DataGridView或BindingSource转换为DataTable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!