locked
how to extract the "New" Value from a DynamicControl control, in a GridView Footer RRS feed

  • Question

  • User-1584522569 posted

    I am learning all about this new DynamicData framework, and it all is very interesting...  But I have a problem.

    I am using the trick where the GridView footer row is used for INSERT.  I have removed all references to the DetailsView and its corresponding datasource, as I just want a simple edit/insert directly in the grid.  When btnInsert is fired, I show the Footer, and it renders a series of DynamicControls (see below).  I can enter data in these controls, everything works fine...  Here are the Columns.

      

    <Columns>
    <asp:TemplateField HeaderText="Row Actions" HeaderStyle-Width="50px">
    <ItemTemplate>
    <asp:LinkButton ID="btnEdit" runat="server" CommandName="Edit" Text="Edit" /><br />
    <asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete"
    Text="Delete" />
    <asp:LinkButton ID="btnSelect" runat="server" CommandName="Select" Text="Select"
    Visible="false" />
    </ItemTemplate>
    <EditItemTemplate>
    <asp:LinkButton ID="btnUpdate" runat="server" CommandName="Update" Text="Update" />
    <asp:LinkButton ID="btnCancel" runat="server" CommandName="Cancel" Text="Cancel" />
    </EditItemTemplate>
    <InsertItemTemplate>
    <asp:LinkButton ID="btnUpdate" runat="server" CommandName="Insert" Text="Insert" />
    <asp:LinkButton ID="btnCancel" runat="server" CommandName="Cancel" Text="Cancel" />
    </InsertItemTemplate>
    <FooterTemplate>
    <asp:LinkButton ID="btnInsert" runat="server" CommandName="Insert" Text="Insert" />
    <asp:LinkButton ID="btnCancelInsert" runat="server" CommandName="Cancel" Text="Cancel"
    CausesValidation="false" />
    </FooterTemplate>
    <HeaderStyle Width="50px" />
    </asp:TemplateField>

    <asp:TemplateField HeaderText="Enabled" HeaderStyle-Width="25px">
    <ItemTemplate>
    <asp:DynamicControl runat="server" DataField="EnabledFlag" />
    </ItemTemplate>
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl8" runat="server" DataField="EnabledFlag" Mode="Insert" />
    </FooterTemplate>
    <InsertItemTemplate>
    <asp:DynamicControl runat="server" DataField="EnabledFlag" Mode="Insert" />
    </InsertItemTemplate>
    <HeaderStyle Width="25px" />
    </asp:TemplateField>

    <asp:TemplateField HeaderText="ItemCode" ConvertEmptyStringToNull="False" SortExpression="ItemCode">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl1" runat="server" DataField="ItemCode" Mode="Edit" />
    </EditItemTemplate>
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl9" runat="server" DataField="ItemCode" Mode="Insert" />
    </FooterTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl1" runat="server" DataField="ItemCode" Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="25px" />
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="Description" SortExpression="Description">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl2" runat="server" DataField="Description" Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl2" runat="server" DataField="Description" Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="100px" />
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl10" runat="server" DataField="Description"
    Mode="Insert" />
    </FooterTemplate>
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="StartDate" SortExpression="StartDate">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl3" runat="server" DataField="StartDate" Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl3" runat="server" DataField="StartDate" Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="50px" />
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl11" runat="server" DataField="StartDate" Mode="Insert" />
    </FooterTemplate>
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="EndDate" SortExpression="EndDate">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl4" runat="server" DataField="EndDate" Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl4" runat="server" DataField="EndDate" Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="50px" />
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl12" runat="server" DataField="EndDate" Mode="Insert" />
    </FooterTemplate>
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="DisplayEndDate" SortExpression="DisplayEndDate">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl5" runat="server" DataField="DisplayEndDate"
    Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl5" runat="server" DataField="DisplayEndDate"
    Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="50px" />
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl13" runat="server" DataField="DisplayEndDate"
    Mode="Insert" />
    </FooterTemplate>
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="Source" SortExpression="Source">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl6" runat="server" DataField="Source" Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl6" runat="server" DataField="Source" Mode="ReadOnly" />
    </ItemTemplate>
    <HeaderStyle Width="50px" />
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl14" runat="server" DataField="Source" Mode="Insert" />
    </FooterTemplate>
    </asp:TemplateField>

    <asp:TemplateField ConvertEmptyStringToNull="False" HeaderText="ProductWatchType"
    SortExpression="ProductWatchType">
    <EditItemTemplate>
    <asp:DynamicControl ID="DynamicControl7" runat="server" DataField="ProductWatchType"
    Mode="Edit" />
    </EditItemTemplate>
    <ItemTemplate>
    <asp:DynamicControl ID="DynamicControl7" runat="server" DataField="ProductWatchType"
    Mode="ReadOnly" />
    </ItemTemplate>
    <FooterTemplate>
    <asp:DynamicControl ID="DynamicControl15" runat="server" DataField="ProductWatchType"
    Mode="Insert" />
    </FooterTemplate>
    <HeaderStyle Width="50px" />
    </asp:TemplateField>

    <asp:TemplateField HeaderStyle-Width="250px" HeaderText="Audit Information">
    <ItemTemplate>
    <span style="font-size: xx-small; font-style: italic; width: 500px">Created:
    <asp:DynamicControl runat="server" DataField="CreatedBy" Mode="ReadOnly" />
    on
    <asp:DynamicControl runat="server" DataField="CreatedDate" Mode="ReadOnly" />
    <br />
    LastUpdated:
    <asp:DynamicControl runat="server" DataField="LastUpdatedBy" Mode="ReadOnly" />
    on
    <asp:DynamicControl runat="server" DataField="LastUpdatedDate" Mode="ReadOnly" />
    </span>
    </ItemTemplate>
    <HeaderStyle Width="250px" />
    </asp:TemplateField>
    </Columns>
     Now, when I try to now Insert this new row using the values that were entered in these DynamicControl controls, I can't seem to get to them!

    I most recently have tried to iterate through the Cells of the Footer Row, looking for the DynamicControls, and adding the DynamicControl.DataField and its corresponding Value to a dictionary, that I want to send to GridDataSource.Insert(IDictionary values).

    But, as I look at the DynamicControl, at its FieldTemplate, I don't see my new values.  They are always blank...  

     

    Have I totally missed the boat on this one?

    Thanks.

    j

    Monday, September 15, 2008 5:55 PM

All replies

  • User-1584522569 posted

     I have given up.  I cannot figure out the magic behind the DetailsView and its Insert logic.  So, I just added a route for Insert, that uses the Insert.aspx page.  And I added a link on my ListDetails.aspx page that uses the GetActionPath("Insert") call on the MetaTable object, to construct a NavigateUrl value.

     

    I still wish someone could de-mystify the Insert logic and how it pulls New Values from Dynamic Controls when used in a DynamicData Website.

    -j

    Wednesday, September 17, 2008 12:03 AM
  • User660823006 posted

    In this case since you are not actually doing databinding you will have to get access to the underlying control inside of the field template that is responsible for the input. There is a property on the field template called DataControl that will give you the underlying control that is used for input. For example on a text field you could do something like: ((TextBox)DynamicControl.FieldTemplate.DataControl).Text. This will get you access to the values without any data binding occuring.

    Wednesday, September 17, 2008 1:33 AM
  • User-1584522569 posted

     I started down that path until i realized that I would have a big switch statement where i typecast the DataControl to a TextBox, CheckBox, DropDownList, etc. to pull out the value... but even worse, since these are FieldTemplateUserControls, they could have a Control that I dont have in my switch statement.... and then I am broken.

     

    So, The real question is:  How does the DetailsView do it?  How can you query a FieldTemplateUserControl or the DynamicControl to get the new value?  Is there some code for the DetailsView that shows how it collects the new values for each field?

     

    Thanks!

     

    -j

    Wednesday, September 17, 2008 6:28 PM
  • User-330204900 posted

    Your problem is that the DetailView has built in support for Insert and the GridView does not. Have you got a version of GridView Insert working under classic ASP.Net GridView?

    Thursday, September 18, 2008 2:08 AM
  • User-1584522569 posted

     Right... the GridView is limited in that it does not natively support insert.

    So, the DetailsView does support insert.  And I went that route with my insert on a separate page. 

    The outstanding question remains:  How does the DetailsView pull values from the DynamicControls that it uses (and specifically the FieldTemplateUserControl controls).  These are autogenerated based on the model partial class data types and UIHint attributes...  All is good there, I understand that.  But I just dont understand how it then gets the data from these controls.  Is there a sample somewhere that shows how the detailsView does this on an insert?

    One last point I would like to make:  I can get a ref to the underlying FieldTemplateUserControl and its corresponding DataControl but I cannot figure out how to get the actual new value from the DataControl without casting to the underlying controls actual type (i.e. TextBox or Checkbox, etc.).  This Does not work for me, as I have a Calender.ascx and Calendar_Edit.ascx that uses TelerikDatePicker today, but maybe a custom one tomorrow.  I dont want to HAVE to cast the DataControl to its actual underlying type.  It would seem that the FieldTemplateUserControl would have a way to get the 'edited' value... for the corresponding DataField... or something..

    I guess its even more complicated as a FieldTemplateUserControl can pull in multiple DataValues.  But, I go back to the UIHint:  It is associated to a DataColumn and so the corresponding FieldTemplateUserControl should really only contain a NEW value for that data column...

    So, How does the DetailsView do this? when using DynamicControl objects?

    Thanks!

     

    -j

    Thursday, September 18, 2008 9:59 AM
  • User-330204900 posted

    One last point I would like to make:  I can get a ref to the underlying FieldTemplateUserControl and its corresponding DataControl but I cannot figure out how to get the actual new value from the DataControl without casting to the underlying controls actual type (i.e. TextBox or Checkbox, etc.).

    Hi j, I was wondering if you cast the FieldTemplate to FieldTemplateUserControl you could then call the ExtractValues method with an IOrderdDictionaly and get the values that way?

    Hope this helps [:D]

    I'm looking into this a I have a FieldTemplare called ChildrenGrid which works on MetaChildren columns which I would like to add Insert option to.

    So I'll get back to you when I have a solution [:D]

    Thursday, September 18, 2008 11:21 AM
  • User-1584522569 posted

     Steve, thanks for the update.

    I saw the ExtractValues property on the FieldTemplateUserControl, but was not sure what its actual purpose is...  Is it used for the control to grab values from the model to use in its rendering? OR is it used to SET the NEW value if this FieldTemplateUserControl is an EDIT/ INSERT control?

    Also, how do you get to it from a containing class, it is protected...

    Thursday, September 18, 2008 3:50 PM
  • User-330204900 posted

    Take this example:

    protected override void ExtractValues(System.Collections.Specialized.IOrderedDictionary dictionary)
    {
    	dictionary[Column.Name] = ConvertEditedValue(DropDownList1.SelectedValue);
    }
    

    Here the ConvertEditedValue extract the value from the DropDownList it returns an IOrderedDictionary which you can then extract the value from try calling the ExtractValues passing in an IOrderedDictionary parameter and debug and have a look at what it contains.

    Hope this helps [:D]

    Thursday, September 18, 2008 4:42 PM
  • User-1584522569 posted

    Take this example:

    protected override void ExtractValues(System.Collections.Specialized.IOrderedDictionary dictionary)
    {
    	dictionary[Column.Name] = ConvertEditedValue(DropDownList1.SelectedValue);
    }
    

     

     

    Steve,

    I did look at the ExtractValues() call, but it is Protected, so I cannot access it.  Here is the routine that I wrote trying to get my new values.  NOTE:  This Does NOT work.

     

    	protected void InsertProductFromFooter()
    	{
    		Dictionary<string, string> values = new Dictionary<string, string>();
    
    		GridViewRow footer = GridView1.FooterRow;
    
    		if (footer != null)
    		{
    			foreach (TableCell cell in footer.Cells)
    			{
    				foreach (Control c in cell.Controls)
    				{var dc = c as DynamicControl;
    					if (dc != null)
    					{
    						var ft = dc.FieldTemplate as FieldTemplateUserControl;
    						if (ft != null)
    						{
    							ft.ExtractValues(values);                           // <<<<<  This method is not accessible
    							//values.Add(dc.DataField, ft.FieldValueEditString);
    						}
    					}
    				}
    			}
    		}
    		else
    			throw new Exception("Cannot find Footer row of Grid.");
    		//Insert here.
    		GridDataSource.Insert(values);
    
    	}
    
      
    Friday, September 19, 2008 11:36 AM
  • User-330204900 posted

    OK J, I'll think somemore [:D]

    Friday, September 19, 2008 2:10 PM
  • User-1584522569 posted

     Hey steve, any luck with this issue?

     

    Thanks!

    -j

    Tuesday, September 23, 2008 4:14 PM
  • User-330204900 posted

    Not yet I've been stuck on something else which I'm nearly done with and then I'll get back this (I want to add insert to my ChildrenGrid FieldTemplate) [:D]

    Tuesday, September 23, 2008 4:27 PM
  • User-330204900 posted

    Hi Jashmead, I decided to go about doing the insert another way:

    I decided that I'd not bother with getting the GridView to do Insert and instead get the ListView to be a bit more dynamic, so heres my article:Dynamic Data Custom Pages: Dynamic/Templated Grid with Insert (Using ListView)

    From Windows Live Writer

    Hope this helps Big Smile

    Thursday, October 9, 2008 4:04 AM
  • User-1584522569 posted

     Thanks for the update.  I will take a read on your article and let you know if this is something that I can use in my current software development.

     

    -j

    Friday, October 10, 2008 2:01 PM