locked
Model Binding with a Nested Control RRS feed

  • Question

  • User1113267749 posted

    Hi,

    I have just started learning Model Binding and Strongly-Typed Data techniques, but I haven't found anything discussing this particular problem yet.

    I have a FormView (which is working), but within its ItemTemplate, some items are contained in a LoginView.

    Here is a simplified version...

    <asp:FormView ID="StaffDetails" runat="server" DataKeyNames="StaffID" ItemType="DLL.Staff"  SelectMethod="StaffDetails_GetItem" UpdateMethod="StaffDetails_UpdateItem">
            <ItemTemplate>
                <h4><%# Item.FName %>&nbsp;<%# Item.LName %></h4> 
                <p><b><%# Item.JobTitle%></b></p>
                        
                        <asp:LoginView ID="EmergencyLoginView" runat="server">
                            <RoleGroups>
                                <asp:RoleGroup Roles="GlobalAdmin">
                                    <ContentTemplate>
                                        <h5>Emergency Information</h5>
                                        <h6>Number They Can Be Reached At:</h6>
                                        <p><%# Item.EmergencyPhone %></p>
                                        <h6>Additional Info:</h6>
                                        <p><%# Item.ECInfo %></p>
                                    </ContentTemplate>
                                </asp:RoleGroup>
                            </RoleGroups>
                        </asp:LoginView>
            </ItemTemplate>
    </asp:FormView>

    The first few items (FirstName, LastName and JobTitle) display fine.

    But the items within that LoginView throw an error: "Item is not declared. It may be inaccessible due to its protection level."

    I assume that this is because the control is nested, and that "Item" within the LoginView has a separate meaning from "Item" outside of it. But I have no idea what the syntax is to refer to the FormView's "Item" from inside that LoginView.

    I have tried "Parent.Item.EmergencyPhone", or referring to the FormView directly... like "StaffDetails.Item.EmergencyPhone"... but they all throw errors.

    I have also tried reverting back to using the older "Eval" syntax...

    <p><%# Eval("EmergencyPhone") %></p>

    Interestingly, that works when the page first loads, but it returns a NULL on postbacks. (For example, if a user goes into EditMode on that FormView, but hits the Cancel button, the data within the LoginView all disappears, while the data outside the LoginView remains).

    I would think that this would be a simple matter, and I just don't know the new model binding syntax well enough, but I cannot find any references to this. Any help would be most appreciated.

    Thanks,

    Tom

    Wednesday, May 4, 2016 2:58 PM

All replies

  • User36583972 posted

    Hi tommyj1112,

    From your description, you can try using <%# DataBinder.Eval(DataBinder.GetDataItem(StaffDetails),"EmergencyPhone") %> in your method. I have made a sample on my side. The following code in my project for your reference.

    HTML:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:FormView ID="StaffDetails" runat="server" DataKeyNames="StaffID">
                    <ItemTemplate>
                        <h4><%# Eval("FName")  %>&nbsp;<%# Eval("LName")  %></h4>
                        <p><b><%# Eval("JobTitle") %></b></p>
    
                        <asp:LoginView ID="EmergencyLoginView" runat="server">
                            <AnonymousTemplate>
                                <h5>Emergency Information</h5>
                                <h6>Number They Can Be Reached At:</h6>
                                <p><%# DataBinder.Eval(DataBinder.GetDataItem(StaffDetails),"EmergencyPhone") %></p>
                                <h6>Additional Info:</h6>
                                <p><%# DataBinder.Eval(DataBinder.GetDataItem(StaffDetails),"ECInfo") %></p>
                            </AnonymousTemplate>
                            <RoleGroups>
                                <asp:RoleGroup Roles="GlobalAdmin">
                                    <ContentTemplate>
                                        <h5>Emergency Information</h5>
                                        <h6>Number They Can Be Reached At:</h6>
                                        <p><%# DataBinder.Eval(DataBinder.GetDataItem(StaffDetails),"EmergencyPhone") %></p>
                                        <h6>Additional Info:</h6>
                                        <p><%# DataBinder.Eval(DataBinder.GetDataItem(StaffDetails),"ECInfo") %></p>
                                    </ContentTemplate>
                                </asp:RoleGroup>
                            </RoleGroups>
                        </asp:LoginView>
                    </ItemTemplate>
                </asp:FormView>
            </div>
            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
        </form>
    </body>
    </html>

    ASPX.CS:

     protected void Page_Load(object sender, EventArgs e)
            {
                if(!IsPostBack)
                {
                    bind();
    
                }
            }
    
            private void bind()
            {
                DataTable tblDatas = new DataTable("Datas");
                DataColumn dc = null;
                dc = tblDatas.Columns.Add("StaffID", Type.GetType("System.Int32"));
                dc.AutoIncrement = true;//
                dc.AutoIncrementSeed = 1;//
                dc.AutoIncrementStep = 1;//
                dc.AllowDBNull = false;
                dc = tblDatas.Columns.Add("FName", Type.GetType("System.String"));
                dc = tblDatas.Columns.Add("LName", Type.GetType("System.String"));
                dc = tblDatas.Columns.Add("JobTitle", Type.GetType("System.String"));
                dc = tblDatas.Columns.Add("EmergencyPhone", Type.GetType("System.String"));
                dc = tblDatas.Columns.Add("ECInfo", Type.GetType("System.String"));
                DataRow newRow;
                for (int i = 0; i < 1; i++)
                {
                    newRow = tblDatas.NewRow();
                    newRow["FName"] = "Type" + i.ToString();
                    newRow["LName"] = "Position_" + (i * 2);
                    newRow["JobTitle"] = "Write In Candidate";
                    newRow["EmergencyPhone"] = " EmergencyPhone_001";
                    newRow["ECInfo"] = "ECInfo_001";
                    tblDatas.Rows.Add(newRow);
                }
                ViewState["dt"] = tblDatas;
                StaffDetails.DataSource = tblDatas;
                StaffDetails.DataBind();
    
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                Response.Write("OK");
            }

    Best Regards,

    Yohann Lu

    Thursday, May 5, 2016 6:46 AM
  • User1113267749 posted

    Thank you for replying.

    However, I notice that you completely abandon the Model Binding/Strongly-Typed Data Controls syntax... which really was the whole point of this exercise.

    Thursday, May 5, 2016 9:05 PM
  • User36583972 posted

    Hi tommyj1112,

    ASP.NET 4.5 introduces strongly typed data controls in the templates.  A new ModelType property has been added to the data controls, and this allows you to specify the type of object that is bound to the control.

    The following introduce some solutions, you can refer it (we should find the suitable methods for solving problems in different scenarios).

    Access parent data in a nested strongly typed repeater:

    http://stackoverflow.com/questions/16344293/access-parent-data-in-a-nested-strongly-typed-repeater

    Best Regards,

    Yohann Lu

    Wednesday, May 11, 2016 10:54 AM