问题
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 aList<T>
, theDataBoundItem
property of each row is of typeT
.You can search on a
Rows
collection ofDataGridView
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