For some reason there is no ManyToMany.ascx or ManyToMany_Edit.ascx controls when using the default asp.NET DD DomainService template.
I am trying to change the ManyToMany.ascx and ManyToMany_Edit.ascx controls from the normal Entity Framework DD template to be able to use with DomainDataSource but am having problems. Please could someone shed some light?
These are the problems I am having:
1 - It works for EntityDataSource
// Register for the DataSource's updating event EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl();
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);
}
// 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);
}
}
}
Hi Pallone, the M:M field template does not work out of the box with DS if you search for ManyToMany_Edit.ascx in this forum you will find several threads one of those does have a solution.
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
1 - From the ascx control that I created, how do I get the DomainDataSource
in the parent Edit.aspx page? The code I tried using FindDataSourceControl does not work. I need to set a variable to the instance that is in the Detail.aspx page so that I can further compose the query, I think.
Try my FindControlRecursive extension method here:
/// <summary>
/// Get the control by searching recursively for it.
/// </summary>
/// <param name="Root">The control to start the search at.</param>
/// <param name="Id">The ID of the control to find</param>
/// <returns>The control the was found or NULL if not found</returns>
public static Control FindControlRecursive(this Control Root, string Id)
{
if (Root.ID == Id)
return Root;
foreach (Control Ctl in Root.Controls)
{
Control FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
/// <summary>
/// Finds the control recursive.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root">The root.</param>
/// <returns></returns>
public static T FindControlRecursive<T>(this Control root) where T : Control
{
var control = root as T;
if (control != null)
return control;
foreach (Control Ctl in root.Controls)
{
T FoundCtl = Ctl.FindControlRecursive<T>();
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
/// <summary>
/// Finds the control recursive.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root">The root.</param>
/// <param name="Id">The id.</param>
/// <returns></returns>
public static T FindControlRecursive<T>(this Control root, string Id) where T : Control
{
var control = root as T;
if (control != null && root.ID == Id)
return control;
foreach (Control Ctl in root.Controls)
{
T FoundCtl = Ctl.FindControlRecursive<T>(Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
/// <summary>
/// Get the Data Control containing the FiledTemplate
/// usually a DetailsView or FormView
/// </summary>
/// <param name="control">
/// Use the current field template as a starting point
/// </param>
/// <returns>
/// A FilterRepeater the control that
/// contains the current control
/// </returns>
public static T GetContainerControl<T>(this Control control) where T : Control
{
var parentControl = control.Parent;
while (parentControl != null)
{
var p = parentControl as T;
if (p != null)
return p;
else
parentControl = parentControl.Parent;
}
return null;
}
/// <summary>
/// Gets the parent control of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="control">The control.</param>
/// <returns></returns>
public static T GetParent<T>(this Control control) where T : Control
{
var parentControl = control.Parent;
while (parentControl != null)
{
var currentParentControl = parentControl as T;
if (currentParentControl != null)
return currentParentControl;
else
parentControl = parentControl.Parent;
}
return null;
}
This is a set of extension methods I use all the time
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
pallone
Member
165 Points
160 Posts
From EntityDataSource to DomainDataSource in DD
Feb 24, 2012 02:38 PM|LINK
Hi,
For some reason there is no ManyToMany.ascx or ManyToMany_Edit.ascx controls when using the default asp.NET DD DomainService template.
I am trying to change the ManyToMany.ascx and ManyToMany_Edit.ascx controls from the normal Entity Framework DD template to be able to use with DomainDataSource but am having problems. Please could someone shed some light?
These are the problems I am having:
1 - It works for EntityDataSource
// Register for the DataSource's updating event
EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl();
It doesn't work for DomainDataSource
DomainDataSource ds = (DomainDataSource )this.FindDataSourceControl();
How do I get the DomainDataSource from within the ascx control?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 - It works for EntityDataSource
// Get the collection of territories for this employee
RelatedEnd entityCollection = (RelatedEnd)Column.EntityTypeProperty.GetValue(e.Entity, null);
DomainDataSource doesn't seem to have an e.Entity property or a e.Context
How do I get the higlighted code below extracted from ManyToMay_Edit.ascx to work with Domain Service DomainDataSource
ascx EntityDataSource Code
-----------------------------------
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);
}
}
}
Cheers
C
sjnaughton
All-Star
27320 Points
5459 Posts
MVP
Re: From EntityDataSource to DomainDataSource in DD
Feb 24, 2012 04:52 PM|LINK
Hi Pallone, the M:M field template does not work out of the box with DS if you search for ManyToMany_Edit.ascx in this forum you will find several threads one of those does have a solution.
Always seeking an elegant solution.
pallone
Member
165 Points
160 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 24, 2012 05:22 PM|LINK
Hi Steve,
I will try to search for it.
Thanks
C
pallone
Member
165 Points
160 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 24, 2012 05:35 PM|LINK
Hi Steve,
I have searched for ManyToMany_Edit.ascx as you suggested and read all posts but none of them have a solution to my problem.
Could you please suggest where else I can find this solution?
Cheers
C
pallone
Member
165 Points
160 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 24, 2012 10:11 PM|LINK
Hi,
Does anyone know a solution to the problem above?
Cheers
C
sjnaughton
All-Star
27320 Points
5459 Posts
MVP
Re: From EntityDataSource to DomainDataSource in DD
Feb 25, 2012 11:33 AM|LINK
Hi Pallone, I have searched the forum and I cannot find the thread that help the M:M field template for DS sorry.
Always seeking an elegant solution.
pallone
Member
165 Points
160 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 25, 2012 12:13 PM|LINK
Hi Steve,
Thanks. I searched as well but could not find it.
I have a couple of questions.
1 - From the ascx control that I created, how do I get the DomainDataSource in the parent Edit.aspx page? The code I tried using FindDataSourceControl does not work. I need to set a variable to the instance that is in the Detail.aspx page so that I can further compose the query, I think.
DomainDataSource ds = (DomainDataSource )this.FindDataSourceControl();
2 - Since the code in the Edit.aspx is generic, how do I detect there if I am dealing with this ManyToMay_Edit.asxc control I am creating?
Cheers
C
sjnaughton
All-Star
27320 Points
5459 Posts
MVP
Re: From EntityDataSource to DomainDataSource in DD
Feb 25, 2012 05:22 PM|LINK
Try my FindControlRecursive extension method here:
/// <summary> /// Get the control by searching recursively for it. /// </summary> /// <param name="Root">The control to start the search at.</param> /// <param name="Id">The ID of the control to find</param> /// <returns>The control the was found or NULL if not found</returns> public static Control FindControlRecursive(this Control Root, string Id) { if (Root.ID == Id) return Root; foreach (Control Ctl in Root.Controls) { Control FoundCtl = FindControlRecursive(Ctl, Id); if (FoundCtl != null) return FoundCtl; } return null; } /// <summary> /// Finds the control recursive. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="root">The root.</param> /// <returns></returns> public static T FindControlRecursive<T>(this Control root) where T : Control { var control = root as T; if (control != null) return control; foreach (Control Ctl in root.Controls) { T FoundCtl = Ctl.FindControlRecursive<T>(); if (FoundCtl != null) return FoundCtl; } return null; } /// <summary> /// Finds the control recursive. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="root">The root.</param> /// <param name="Id">The id.</param> /// <returns></returns> public static T FindControlRecursive<T>(this Control root, string Id) where T : Control { var control = root as T; if (control != null && root.ID == Id) return control; foreach (Control Ctl in root.Controls) { T FoundCtl = Ctl.FindControlRecursive<T>(Id); if (FoundCtl != null) return FoundCtl; } return null; } /// <summary> /// Get the Data Control containing the FiledTemplate /// usually a DetailsView or FormView /// </summary> /// <param name="control"> /// Use the current field template as a starting point /// </param> /// <returns> /// A FilterRepeater the control that /// contains the current control /// </returns> public static T GetContainerControl<T>(this Control control) where T : Control { var parentControl = control.Parent; while (parentControl != null) { var p = parentControl as T; if (p != null) return p; else parentControl = parentControl.Parent; } return null; } /// <summary> /// Gets the parent control of type T. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="control">The control.</param> /// <returns></returns> public static T GetParent<T>(this Control control) where T : Control { var parentControl = control.Parent; while (parentControl != null) { var currentParentControl = parentControl as T; if (currentParentControl != null) return currentParentControl; else parentControl = parentControl.Parent; } return null; }This is a set of extension methods I use all the time
Always seeking an elegant solution.
pallone
Member
165 Points
160 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 25, 2012 11:51 PM|LINK
Hi Steve,
Thanks for the code. I will try to use it.
Do you also have any ideas of how to detect in the Edit.aspx when I am dealing with the ManyToMany_edit.ascx control I am creating?
I was wondering if I could extend the query in the Query Extender there. For example in Edit.aspx:
protected void CustExpr_Querying(object sender, CustomExpressionEventArgs e)
{
if(ManyToMany.asxc)
{
e.Query = e.Query.Cast<tblWorkGroup>().Where(
wg => wg.CompanieID == DropDwonList.SeldctedValue);
}
}
Cheers
C
Decker Dong ...
All-Star
118619 Points
18779 Posts
Re: From EntityDataSource to DomainDataSource in DD
Feb 25, 2012 11:58 PM|LINK
Hello pallone:)
Hard to do that。I think you'd better use this statament for a general way——because One-To-Many is a kind of Many-To-Many。
Reguards!