I am attempting to implement a master-details view in the following way:
My Edit.aspx is a custom dynamic data form using a Formview to contain a TabContainer control. Most of the tabs are displaying the fields on the master record. I want to put the details list on one of the tabs. Since the TabContainer is totally defined within
the Formview's EditItemTemplate, this means I need to put my details list inside the definition of the Formview. Is this a scenario that is likely to work. My quick tests did not appear to work, but I am likely missing something. The two strategies I have
tried were :
1. Put a Gridview and its associated datasource into the appropriate tabpanel.
2. Create a custom field template which is basically a clone of the standard ListDetails.aspx page. This works in so far as it displays the data correctly, but all updates and inserts seem to get in a tangle. Is it worth pursuing this line of attack, or
is it fundamentally not possible.
2. Create a custom field template which is basically a clone of the standard ListDetails.aspx page. This works in so far as it displays the data correctly, but all updates and inserts seem to get in a tangle. Is it worth pursuing this line of attack, or is
it fundamentally not possible.
I would pursue the 2 which I think has thebest change of success.
Dynamic Data
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
Thanks for the confirmation. Thats pretty much the only option I can see working. Now my challenge is to figure out how to get the whole thing to actually work. As I said earlier, the grid and details views come up ok aand display the data ok. The inser
and edit links go into the edit mode correctly on the details view, but when I commit the change, I get an empty control. As far as I can tell, the values from the controls are coming in correctly in the Form collection on the page, so I am assuming there
is just some subtlety of the Dynamic Data plumbing that I don't understand. If anyone has any suggested reading that I can get into this a bit more deeply rther than just operating in brain dead mode and saying "oh dear it doesn't work", it would be good to
get a sense of what should be happening, and then I can hopefully make it happen.
Hi Nigel, I'm 90% there I've got it updating & deleting but I've not got it generating all the columns. So the collections are not there and I can't seem to get the where clause to work.
May be I'm being a bit dumb again [:(]
What I've done is create a FieldTemplate from a List.aspxPageTemplate and added some bits to get the rest to work. I think it would be easy if I could customize the DynamicDataManager to that it used the table I wanted not the one from the url.
Anyway here's what I've got so far [:D]
GridView_Edit.ascx:
<%@ Control Language="C#" CodeFile="GridView_Edit.ascx.cs" Inherits="GridView_EditField" %>
<%@ Register src="~/DynamicData/Content/GridViewPager.ascx" mce_src="~/DynamicData/Content/GridViewPager.ascx" tagname="GridViewPager" tagprefix="asp" %>
<asp:DynamicDataManager
runat="server"
ID="DynamicDataManager1"
AutoLoadForeignKeys="true" />
<asp:ScriptManagerProxy
runat="server"
ID="ScriptManagerProxy1" />
<asp:ValidationSummary
runat="server"
ID="ValidationSummary1"
EnableClientScript="true"
HeaderText="List of validation errors" />
<asp:DynamicValidator
runat="server"
ID="GridViewValidator"
ControlToValidate="GridView1"
Display="None" />
<asp:GridView
runat="server"
ID="GridView1"
DataSourceID="GridDataSource"
AllowPaging="True"
AllowSorting="True"
AutoGenerateColumns="true"
AutoGenerateDeleteButton="true"
AutoGenerateEditButton="true"
CssClass="gridview">
<Columns>
</Columns>
<PagerStyle CssClass="footer"/>
<PagerTemplate>
<asp:GridViewPager runat="server" />
</PagerTemplate>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
<asp:LinqDataSource
runat="server"
ID="GridDataSource"
EnableDelete="true">
</asp:LinqDataSource>
and the code behind:
using System;
using System.Web.DynamicData;
using System.Web.UI.WebControls;
public partial class GridView_EditField : FieldTemplateUserControl
{
protected MetaTable table;
protected void Page_Init(object sender, EventArgs e)
{
var column = Column as MetaChildrenColumn;
if (column != null)
{
GridDataSource.ContextTypeName = column.ChildTable.DataContextType.Name;
GridDataSource.TableName = column.ChildTable.Name;
GridDataSource.EnableDelete = true;
GridDataSource.EnableUpdate = true;
String[] keys = new String[column.ChildTable.PrimaryKeyColumns.Count];
int i = 0;
foreach (var keyColumn in column.ChildTable.PrimaryKeyColumns)
{
keys[i] = keyColumn.Name;
i++;
}
GridView1.DataKeyNames = keys;
//DynamicDataManager1.RegisterControl(GridView1, false);
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString.Count > 0)
{
String value = Request.QueryString[0];
String name = Request.QueryString.AllKeys[0];
var param = new Parameter();
param.Name = name;
param.DefaultValue = value;
GridDataSource.WhereParameters.Add(param); GridDataSource.AutoGenerateWhereClause = true; // note when this is commented out I get a type error
}
}
}
Hope this helps [:D]
Dynamic DataCustom Field TemplatesGridView
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Web.DynamicData;
using System.Data.Linq.Mapping;
public partial class GridView_EditField : FieldTemplateUserControl
{
protected System.Web.DynamicData.MetaTable table;
protected void Page_Init(object sender, EventArgs e)
{
var column = Column as MetaChildrenColumn;
if (column != null)
{
GridDataSource.ContextTypeName = column.ChildTable.DataContextType.Name;
GridDataSource.TableName = column.ChildTable.Name;
GridDataSource.EnableDelete = true;
GridDataSource.EnableUpdate = true;
table = GridDataSource.GetTable();
GridView1.ColumnsGenerator = new GridViewColumnGenerator(table);
String[] keys = new String[column.ChildTable.PrimaryKeyColumns.Count];
int i = 0;
foreach (var keyColumn in column.ChildTable.PrimaryKeyColumns)
{
keys[i] = keyColumn.Name;
i++;
}
GridView1.DataKeyNames = keys;
if (Request.QueryString.Count > 0)
{
String value = Request.QueryString[0];
String name = Request.QueryString.AllKeys[0];
var fkColumn = table.GetColumn(name);
var param = new Parameter();
param.Name = name;
param.Type = Type.GetTypeCode(fkColumn.ColumnType);
param.DefaultValue = value;
GridDataSource.WhereParameters.Add(param);
GridDataSource.AutoGenerateWhereClause = true;
}
//DynamicDataManager1.RegisterControl(GridView1, false);
}
}
}
public class GridViewColumnGenerator : IAutoFieldGenerator
{
protected System.Web.DynamicData.MetaTable _table;
public GridViewColumnGenerator(System.Web.DynamicData.MetaTable table)
{
_table = table;
}
public ICollection GenerateFields(Control control)
{
List oFields = new List();
foreach (var column in _table.Columns)
{
// carry on the loop at the next column
// if scaffold table is set to false or DenyRead
if (!column.Scaffold)
continue;
DynamicField f = new DynamicField();
f.DataField = column.Name;
oFields.Add(f);
}
return oFields;
}
}
Hope this helps [:D]
P.S. I think this would have been much easyer if we had more control of the DynamicDataManager such as setting the table, where clause etc. [:D]
Dynamic DataIAutoFieldGenratorCustom Field TemplatesGridView
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
Hey Steve, Really nice piece of work. I am unworthy (and very impressed). What I don't entirely get is why the Dynamic Data Manager fails to work. When I tried the same thing, I was using the Manager, and it worked for displaying the columns, but didn't
work for the updates. So I guess youve replaced some of what it does. Still it woudl be nice to really get it.
Of course every good answer deserves another question - because if you were feeling dumb, then I am really dumb. I seem to be failing at every step of the way here. To implement an insert, we need to put a details view in with the grid (as in the ListDetails)
(or am I really being dumb). So in the normal ListDetails page, the connection between the two is taken care of by the dynamic data manager, In this case, I have added a details view as follows below the grid view :
Then I have hooked in a field generator for the rows in the details view, and have set up the where clause in the same way as for the grid. Now I can successfully insert rows to my hearts content. The problem is that the grid does not get updated after
each insert. As soon as I refresh the page I can see all the new records, but after each insert nothing. I presume there is yet another secret handshake to manually connect the two controls. Any ideas?
What I don't entirely get is why the Dynamic Data Manager fails to work. When I tried the same thing, I was using the Manager, and it worked for displaying the columns, but didn't work for the updates.
Hi Nigel, the reason it dosn't work with DynamicDataManager is that the DynamicDataManager gets it's table info ultimatly from the URL
i.e.
http://localhost:56273/DD_VB_NW/Categories/Edit.aspx?CategoryID=2
All the BOLD ITALIC are bits that the DynamicDataManager gets info from
table, PK
So when you used it it was trying to setup the GridView with contradicting information to your
LinqDataSource.
Hope that explains it a bit [:D]
Dynamic DataCustom Field TemplatesGridView
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
Nigel Basel
Member
5 Points
12 Posts
Implementing a Master-Details view in Dynamic Data
Aug 06, 2008 04:47 AM|LINK
Hi All
I am attempting to implement a master-details view in the following way:
My Edit.aspx is a custom dynamic data form using a Formview to contain a TabContainer control. Most of the tabs are displaying the fields on the master record. I want to put the details list on one of the tabs. Since the TabContainer is totally defined within the Formview's EditItemTemplate, this means I need to put my details list inside the definition of the Formview. Is this a scenario that is likely to work. My quick tests did not appear to work, but I am likely missing something. The two strategies I have tried were :
1. Put a Gridview and its associated datasource into the appropriate tabpanel.
2. Create a custom field template which is basically a clone of the standard ListDetails.aspx page. This works in so far as it displays the data correctly, but all updates and inserts seem to get in a tangle. Is it worth pursuing this line of attack, or is it fundamentally not possible.
Thanks for any thoughts and suggestions.
Nigel
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 06, 2008 09:09 PM|LINK
I would pursue the 2 which I think has thebest change of success.
Dynamic Data
Always seeking an elegant solution.
Nigel Basel
Member
5 Points
12 Posts
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 06:56 AM|LINK
Hi again Steve,
Thanks for the confirmation. Thats pretty much the only option I can see working. Now my challenge is to figure out how to get the whole thing to actually work. As I said earlier, the grid and details views come up ok aand display the data ok. The inser and edit links go into the edit mode correctly on the details view, but when I commit the change, I get an empty control. As far as I can tell, the values from the controls are coming in correctly in the Form collection on the page, so I am assuming there is just some subtlety of the Dynamic Data plumbing that I don't understand. If anyone has any suggested reading that I can get into this a bit more deeply rther than just operating in brain dead mode and saying "oh dear it doesn't work", it would be good to get a sense of what should be happening, and then I can hopefully make it happen.
cheers
Nigel
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 09:53 AM|LINK
Hi Nigel, I'm 90% there I've got it updating & deleting but I've not got it generating all the columns. So the collections are not there and I can't seem to get the where clause to work.
May be I'm being a bit dumb again [:(]
What I've done is create a FieldTemplate from a List.aspx PageTemplate and added some bits to get the rest to work. I think it would be easy if I could customize the DynamicDataManager to that it used the table I wanted not the one from the url.
Anyway here's what I've got so far [:D]
GridView_Edit.ascx:
<%@ Control Language="C#" CodeFile="GridView_Edit.ascx.cs" Inherits="GridView_EditField" %> <%@ Register src="~/DynamicData/Content/GridViewPager.ascx" mce_src="~/DynamicData/Content/GridViewPager.ascx" tagname="GridViewPager" tagprefix="asp" %> <asp:DynamicDataManager runat="server" ID="DynamicDataManager1" AutoLoadForeignKeys="true" /> <asp:ScriptManagerProxy runat="server" ID="ScriptManagerProxy1" /> <asp:ValidationSummary runat="server" ID="ValidationSummary1" EnableClientScript="true" HeaderText="List of validation errors" /> <asp:DynamicValidator runat="server" ID="GridViewValidator" ControlToValidate="GridView1" Display="None" /> <asp:GridView runat="server" ID="GridView1" DataSourceID="GridDataSource" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="true" AutoGenerateDeleteButton="true" AutoGenerateEditButton="true" CssClass="gridview"> <Columns> </Columns> <PagerStyle CssClass="footer"/> <PagerTemplate> <asp:GridViewPager runat="server" /> </PagerTemplate> <EmptyDataTemplate> There are currently no items in this table. </EmptyDataTemplate> </asp:GridView> <asp:LinqDataSource runat="server" ID="GridDataSource" EnableDelete="true"> </asp:LinqDataSource>and the code behind:
Hope this helps [:D]
Dynamic Data Custom Field Templates GridView
Always seeking an elegant solution.
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 10:32 AM|LINK
OK I've fixed the Where clause, see this new Page_Init:
protected void Page_Init(object sender, EventArgs e) { var column = Column as MetaChildrenColumn; if (column != null) { GridDataSource.ContextTypeName = column.ChildTable.DataContextType.Name; GridDataSource.TableName = column.ChildTable.Name; GridDataSource.EnableDelete = true; GridDataSource.EnableUpdate = true; table = GridDataSource.GetTable(); String[] keys = new String[column.ChildTable.PrimaryKeyColumns.Count]; int i = 0; foreach (var keyColumn in column.ChildTable.PrimaryKeyColumns) { keys[i] = keyColumn.Name; i++; } GridView1.DataKeyNames = keys; if (Request.QueryString.Count > 0) { String value = Request.QueryString[0]; String name = Request.QueryString.AllKeys[0]; var fkColumn = table.GetColumn(name); var param = new Parameter(); param.Name = name; param.Type = Type.GetTypeCode(fkColumn.ColumnType); param.DefaultValue = value; GridDataSource.WhereParameters.Add(param); GridDataSource.AutoGenerateWhereClause = true; } //DynamicDataManager1.RegisterControl(GridView1, false); } }See the BOLD ITALIC line [:D]Dynamic Data Custom Field Templates GridView
Always seeking an elegant solution.
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 10:40 AM|LINK
And now the finished code behind [;)]
using System; using System.Data; using System.Configuration; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Xml.Linq; using System.Web.DynamicData; using System.Data.Linq.Mapping; public partial class GridView_EditField : FieldTemplateUserControl { protected System.Web.DynamicData.MetaTable table; protected void Page_Init(object sender, EventArgs e) { var column = Column as MetaChildrenColumn; if (column != null) { GridDataSource.ContextTypeName = column.ChildTable.DataContextType.Name; GridDataSource.TableName = column.ChildTable.Name; GridDataSource.EnableDelete = true; GridDataSource.EnableUpdate = true; table = GridDataSource.GetTable(); GridView1.ColumnsGenerator = new GridViewColumnGenerator(table); String[] keys = new String[column.ChildTable.PrimaryKeyColumns.Count]; int i = 0; foreach (var keyColumn in column.ChildTable.PrimaryKeyColumns) { keys[i] = keyColumn.Name; i++; } GridView1.DataKeyNames = keys; if (Request.QueryString.Count > 0) { String value = Request.QueryString[0]; String name = Request.QueryString.AllKeys[0]; var fkColumn = table.GetColumn(name); var param = new Parameter(); param.Name = name; param.Type = Type.GetTypeCode(fkColumn.ColumnType); param.DefaultValue = value; GridDataSource.WhereParameters.Add(param); GridDataSource.AutoGenerateWhereClause = true; } //DynamicDataManager1.RegisterControl(GridView1, false); } } } public class GridViewColumnGenerator : IAutoFieldGenerator { protected System.Web.DynamicData.MetaTable _table; public GridViewColumnGenerator(System.Web.DynamicData.MetaTable table) { _table = table; } public ICollection GenerateFields(Control control) { List oFields = new List(); foreach (var column in _table.Columns) { // carry on the loop at the next column // if scaffold table is set to false or DenyRead if (!column.Scaffold) continue; DynamicField f = new DynamicField(); f.DataField = column.Name; oFields.Add(f); } return oFields; } }Hope this helps [:D]
P.S. I think this would have been much easyer if we had more control of the DynamicDataManager such as setting the table, where clause etc. [:D]
Dynamic Data IAutoFieldGenrator Custom Field Templates GridView
Always seeking an elegant solution.
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 11:49 AM|LINK
And here is a post on my blog detailing the above Dynamic Data and Field Templates - An Advanced FieldTemplate with a GridView
Hope this helps [:D]
Dynamic Data IAutoFieldGenrator Custom Field Templates GridView
Always seeking an elegant solution.
Nigel Basel
Member
5 Points
12 Posts
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 08:13 PM|LINK
Hey Steve, Really nice piece of work. I am unworthy (and very impressed). What I don't entirely get is why the Dynamic Data Manager fails to work. When I tried the same thing, I was using the Manager, and it worked for displaying the columns, but didn't work for the updates. So I guess youve replaced some of what it does. Still it woudl be nice to really get it.
Of course every good answer deserves another question - because if you were feeling dumb, then I am really dumb. I seem to be failing at every step of the way here. To implement an insert, we need to put a details view in with the grid (as in the ListDetails) (or am I really being dumb). So in the normal ListDetails page, the connection between the two is taken care of by the dynamic data manager, In this case, I have added a details view as follows below the grid view :
<asp:Panel ID="DetailsPanel" runat="server"> <asp:DetailsView ID="DetailsView1" runat="server" DataSourceID="DetailsDataSource" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true" AutoGenerateInsertButton="true" DefaultMode="Insert"> </asp:DetailsView> <asp:LinqDataSource ID="DetailsDataSource" runat="server" EnableDelete="true" EnableInsert="true" EnableUpdate="true" ContextTypeName="TextAndWin.Data.DataModelDataContext" TableName="Triggers"> <WhereParameters> <asp:DynamicControlParameter ControlId="GridView1" /> </WhereParameters> </asp:LinqDataSource> </asp:Panel>Then I have hooked in a field generator for the rows in the details view, and have set up the where clause in the same way as for the grid. Now I can successfully insert rows to my hearts content. The problem is that the grid does not get updated after each insert. As soon as I refresh the page I can see all the new records, but after each insert nothing. I presume there is yet another secret handshake to manually connect the two controls. Any ideas?
cheers
Nigel
Nigel Basel
Member
5 Points
12 Posts
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 08:31 PM|LINK
Ok - answered my own question , all I needed to do was to rebind the grid after the insert was complete. Now its all working.
Thanks Steve once again..
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Implementing a Master-Details view in Dynamic Data
Aug 07, 2008 09:26 PM|LINK
Hi Nigel, the reason it dosn't work with DynamicDataManager is that the DynamicDataManager gets it's table info ultimatly from the URL
i.e.
http://localhost:56273/DD_VB_NW/Categories/Edit.aspx?CategoryID=2
All the BOLD ITALIC are bits that the DynamicDataManager gets info from table, PK
So when you used it it was trying to setup the GridView with contradicting information to your LinqDataSource.
Hope that explains it a bit [:D]
Dynamic Data Custom Field Templates GridView
Always seeking an elegant solution.