これは、今のところ、ManyToMany_edit.ascx.csにあるものです。
public void Page_Load(object sender, EventArgs e) {
// Register for the DataSource's updating event
EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl();
// This field template is used both for Editing and Inserting
ds.Updating += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting);
ds.Inserting += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting);
}
void DataSource_UpdatingOrInserting(object sender, EntityDataSourceChangingEventArgs e) {
MetaTable childTable = ChildrenColumn.ChildTable;
// Comments assume employee/territory for illustration, but the code is generic
// Get the collection of territories for this employee
RelatedEnd entityCollection = (RelatedEnd)Column.EntityTypeProperty.GetValue(e.Entity, null);
// In Edit mode, make sure it's loaded (doesn't make sense in Insert mode)
if (Mode == DataBoundControlMode.Edit && !entityCollection.IsLoaded) {
entityCollection.Load();
}
// Get an IList from it (i.e. the list of territories for the current employee)
// REVIEW: we should be using EntityCollection directly, but EF doesn't have a
// non generic type for it. They will add this in vnext
IList entityList = ((IListSource)entityCollection).GetList();
// Go through all the territories (not just those for this employee)
foreach (object childEntity in childTable.GetQuery(e.Context)) {
// Check if the employee currently has this territory
bool isCurrentlyInList = entityList.Contains(childEntity);
// Find the checkbox for this territory, which gives us the new state
string pkString = childTable.GetPrimaryKeyString(childEntity);
ListItem listItem = CheckBoxList1.Items.FindByValue(pkString);
if (listItem == null)
continue;
// If the states differs, make the appropriate add/remove change
if (listItem.Selected) {
if (!isCurrentlyInList)
entityList.Add(childEntity);
}
else {
if (isCurrentlyInList)
entityList.Remove(childEntity);
}
}
}
protected void gvMyGrid_DataBound(object sender, EventArgs e)
{
}
protected void CheckBoxList1_DataBound(object sender, EventArgs e) {
MetaTable childTable = ChildrenColumn.ChildTable;
// Comments assume employee/territory for illustration, but the code is generic
IList entityList = null;
ObjectContext objectContext = null;
if (Mode == DataBoundControlMode.Edit) {
object entity;
ICustomTypeDescriptor rowDescriptor = Row as ICustomTypeDescriptor;
if (rowDescriptor != null) {
// Get the real entity from the wrapper
entity = rowDescriptor.GetPropertyOwner(null);
} else {
entity = Row;
}
// Get the collection of territories for this employee and make sure it's loaded
RelatedEnd entityCollection = Column.EntityTypeProperty.GetValue(entity, null) as RelatedEnd;
if (entityCollection == null) {
throw new InvalidOperationException(String.Format("The ManyToMany template does not support the collection type of the '{0}' column on the '{1}' table.", Column.Name, Table.Name));
}
if (!entityCollection.IsLoaded) {
entityCollection.Load();
}
// Get an IList from it (i.e. the list of territories for the current employee)
// REVIEW: we should be using EntityCollection directly, but EF doesn't have a
// non generic type for it. They will add this in vnext
entityList = ((IListSource)entityCollection).GetList();
// Get the current ObjectContext
// REVIEW: this is quite a dirty way of doing this. Look for better alternative
ObjectQuery objectQuery = (ObjectQuery)entityCollection.GetType().GetMethod(
"CreateSourceQuery").Invoke(entityCollection, null);
objectContext = objectQuery.Context;
}
// Go through all the territories (not just those for this employee)
foreach (object childEntity in childTable.GetQuery(objectContext)) {
MetaTable actualTable = MetaTable.GetTable(childEntity.GetType());
// Create a checkbox for it
ListItem listItem = new ListItem(
actualTable.GetDisplayString(childEntity),
actualTable.GetPrimaryKeyString(childEntity));
// Make it selected if the current employee has that territory
if (Mode == DataBoundControlMode.Edit) {
listItem.Selected = entityList.Contains(childEntity);
}
CheckBoxList1.Items.Add(listItem);
}
}
public override Control DataControl {
get {
return gvMyGrid;
}
}