This is a migrated thread and some comments may be shown as answers.

Entity Framework complex types error using radgrid edit template

1 Answer 82 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Keith
Top achievements
Rank 1
Keith asked on 13 Mar 2014, 05:34 PM
I have run into an issue trying to use the edit form template on a radgrid bound to an objectdatasource connected to a entity framework data model that uses complex types. It works fine when you edit an existing record but gives an error when adding a new record. Below is the code for a simple demo that I set up using a list of objects. In the below example if I edit a record it all works fine but if I add a record it throws an error "DataBinding: 'Telerik.Web.UI.GridInsertionObject' does not contain a property with the name 'person'.". Any ideas of a work around?

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
        </Scripts>
    </telerik:RadScriptManager>

    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
    </telerik:RadAjaxManager>
    <div>
        <telerik:RadGrid ID="grdData" runat="server"
        AllowSorting="True" GridLines="Vertical" AllowPaging="True" PageSize="50"
        AutoGenerateColumns="False" Width="800px"  DataSourceID="odsData"
        OnDeleteCommand="grdData_DeleteCommand" OnInsertCommand="grdData_InsertCommand" OnUpdateCommand="grdData_UpdateCommand" >
        <MasterTableView GridLines="Vertical" CommandItemDisplay="Top" DataKeyNames="id" EditMode="PopUp">
            <Columns>
                <telerik:GridEditCommandColumn ButtonType="ImageButton" ItemStyle-Width="25" />
                <telerik:GridBoundColumn HeaderText="First Name"  DataField="person.name" SortExpression="name" UniqueName="name" />
                <telerik:GridBoundColumn HeaderText="Email"  DataField="person.email" SortExpression="email" UniqueName="email" />
                <telerik:GridCheckBoxColumn HeaderText="Sales Rep"  DataField="salesRep" SortExpression="salesRep" UniqueName="salesRep" />
                <telerik:GridButtonColumn ConfirmText="Are you sure you want to delete this item?" ConfirmDialogType="RadWindow" 
                    ConfirmTitle="Delete" ButtonType="ImageButton" CommandName="Delete" ItemStyle-Width="25" />
            </Columns>
            <EditFormSettings EditFormType="Template"  >
                <PopUpSettings Width="400px" Modal="true" />
                <FormTemplate>
                    <div style="padding: 10px; text-align: left;">
                        <div><asp:Label ID="Label1" runat="server" Text="Name: " /></div>
                        <div>
                            <asp:TextBox ID="fldFirstName" runat="server" Text='<%# Bind("person.name") %>' Width="300" MaxLength="50" TabIndex="1" />
                        </div>
                        <div>
                            <asp:RequiredFieldValidator ID="valNameRequired" runat="server" ErrorMessage="Name Required" ControlToValidate="fldFirstName" />
                        </div>
                        <div><asp:Label ID="Label4" runat="server" Text="Email: " /></div>
                        <div>
                            <asp:TextBox ID="fldEMail" runat="server" Text='<%# Bind("person.email") %>' Width="300" MaxLength="50" TabIndex="3" />
                        </div>
                        <div>
                            <asp:RequiredFieldValidator ID="valEmailRequired" runat="server" ErrorMessage="Email Required" ControlToValidate="fldEmail" Display="dynamic" />
                            <asp:RegularExpressionValidator ID="valEmail" runat="server" ControlToValidate="fldEmail" ErrorMessage="Enter a valid Email" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" />
                        </div>
                        <div><asp:Label ID="Label6" runat="server" Text="Sales Rep: " /><asp:CheckBox ID="cbxSalesRep" runat="server" Checked='<%# Bind("salesRep") %>' /></div>
                        <div>
                            <asp:Button ID="btnSave" Text="Save" runat="server" CommandName='<%# (Container is GridEditFormInsertItem) ? "PerformInsert" : "Update" %>' Width="100" TabIndex="10" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                            <asp:Button ID="btnCancel" Text="Cancel" runat="server" CausesValidation="False" CommandName="Cancel" Width="100" TabIndex="11" />
                        </div>
                    </div>
                </FormTemplate>
            </EditFormSettings>
        </MasterTableView>
    </telerik:RadGrid>
    </div>
    <telerik:RadWindowManager ID="RadWindowManager" runat="server" />

    <asp:ObjectDataSource ID="odsData" runat="server" TypeName="UserData" SelectMethod="getUsers" DataObjectTypeName="UserData+User" />
    </form>
</body>
</html>



using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Xml.Serialization;
using System.Text;
using Telerik.Web.UI;

public partial class Default : System.Web.UI.Page
{
    public UserData userData = new UserData();

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {

        }
    }

    protected void grdData_InsertCommand(object sender, Telerik.Web.UI.GridCommandEventArgs e)
    {
        var editableItem = ((GridEditableItem)e.Item);

        Hashtable values = new Hashtable();
        editableItem.ExtractValues(values);
        UserData.User user = new UserData.User();
        user.person.name = (string)values["person.name"];
        user.person.email = (string)values["person.email"];
        user.salesRep = bool.Parse(values["salesRep"].ToString());
        userData.updateUser(user);
    }

    protected void grdData_UpdateCommand(object sender, Telerik.Web.UI.GridCommandEventArgs e)
    {
        var editableItem = ((GridEditableItem)e.Item);
        var id = (int)editableItem.GetDataKeyValue("id");

        UserData.User user = userData.getUserById(id);
        Hashtable values = new Hashtable();
        editableItem.ExtractValues(values);
        user.person.name = (string)values["person.name"];
        user.person.email = (string)values["person.email"];
        user.salesRep = bool.Parse(values["salesRep"].ToString());
        userData.updateUser(user);
    }

    protected void grdData_DeleteCommand(object sender, Telerik.Web.UI.GridCommandEventArgs e)
    {
        var editableItem = ((GridEditableItem)e.Item);
        var id = (int)editableItem.GetDataKeyValue("id");

        userData.deleteUser(id);
    }
}

public class UserData
{
    List<User> userData;

    public UserData()
    {  
        if (File.Exists("c:\\temp\\testdata.xml"))
            userData = XSerial.Load<List<User>>("c:\\temp\\testdata.xml");
        else
        {
            userData = new List<User>();
            userData.Add(new User(1, new Person("Fred Flintstone", "fredflintstone@gmail.com"), false));
            userData.Add(new User(2, new Person("Barney Rubble", "brubble@gmail.com"), false));
            userData.Add(new User(3, new Person("Mr. Slate", "mslate@slatequarry.com"), false));
            saveData();
        }
    }

    public void saveData()
    {
        XSerial.Save<List<User>>("c:\\temp\\testdata.xml", userData);
    }

    public List<User> getUsers()
    {
        return userData;
    }

    public User getUserById(int id)
    {
        int i = 0;
        while(i < userData.Count && userData[i].id != id)
            i++;
        return userData[i];
    }

    public void insertUser(User user)
    {
        int nextId = 1;

        int i = 0;
        while (i < userData.Count && userData[i].id != user.id)
        {
            if (userData[i].id > nextId)
                nextId = userData[i].id + 1;
            i++;
        }

        user.id = nextId;
        userData.Add(user);

        XSerial.Save<List<User>>("c:\\temp\\testdata.xml", userData);
    }

    public void updateUser(User user)
    {
        int i = 0;
        while (i < userData.Count && userData[i].id != user.id)
            i++;

        userData[i] = user;

        XSerial.Save<List<User>>("c:\\temp\\testdata.xml", userData);
    }

    public void deleteUser(int id)
    {
        int i = 0;
        while (i < userData.Count && userData[i].id != id)
            i++;

        userData.RemoveAt(i);

        XSerial.Save<List<User>>("c:\\temp\\testdata.xml", userData);
    }

    public class Person
    {
        private string _name;
        private string _email;

        public string name
        {
            get { return _name; }
            set { _name = value; }
        }

        public string email
        {
            get { return _email; }
            set { _email = value; }
        }

        public Person()
        {
            _name = "";
            _email = "";
        }

        public Person(string name, string email)
        {
            _name = name;
            _email = email;
        }
    }

    public class User
    {
        private int _id;
        private Person _person;
        private bool _salesRep;

        public int id
        {
            get { return _id; }
            set { _id = value; }
        }

        public Person person
        {
            get { return _person; }
            set { _person = value; }
        }

        public bool salesRep
        {
            get { return _salesRep; }
            set { _salesRep = value; }
        }

        public User()
        {
            _id = 0;
            _person = new Person();
            _salesRep = false;
        }

        public User(int id, Person person, bool salesRep)
        {
            _id = id;
            _person = person;
            _salesRep = salesRep;
        }
    }
}

 /// <summary>
/// Serializer class.  Load and Save classes from/to XML files.
/// </summary>
public class XSerial
{
    /// <summary>
    /// Load a class from a serialized XML file.
    /// </summary>
    /// <param name="filename">full path or path relative to the XML file</param>
    /// <param name="t">type of the class that is being retrieved (Use typeof(ClassName))</param>
    /// <returns>A populated version of the class, or null on failure</returns>
    /// <exception cref="Exception">Can throw several exceptions for IO and serialization loading</exception>
    public static T Load<T>(string filename)
    {
        T ob = default(T);
            using (Stream s = File.Open(filename, FileMode.Open))
            {
                StreamReader sr = new StreamReader(s);
                ob = DeserializeObject<T>(sr.ReadToEnd());
                s.Close();
            }
        return ob;
    }

    /// <summary>
    /// Save an instance of a class to an XML file
    /// </summary>
    /// <param name="filename">Full or relative path to the file</param>
    /// <param name="cls">Class to serialize and save.</param>
    /// <param name="t">Type of the class (use: typeof(ClassName)</param>
    /// <returns>True on success, False on failure</returns>
    public static void Save<T>(string filename, T cls)
    {
        using (Stream s = File.Open(filename, FileMode.Create))
        {
            using (StreamWriter sw = new StreamWriter(s))
            {
                sw.Write( SerializeObject<T>(cls) );
                sw.Close();
                s.Close();
                return;
            }
        }
    }


    /// <summary>
    /// Serialize the object into an XML format
    /// </summary>
    /// <typeparam name="T">Type of object to serialize</typeparam>
    /// <param name="pObject">the object to serialize</param>
    /// <returns>a string representing the XML version of the object</returns>
    public static String SerializeObject<T>(T pObject)
    {
        MemoryStream memoryStream = new MemoryStream();
        UTF8Encoding encoding = new UTF8Encoding();

        XmlSerializer xs = new XmlSerializer(typeof(T));
        System.Xml.XmlTextWriter xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
        xs.Serialize(xmlTextWriter, (object) pObject);
        memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
        return encoding.GetString(memoryStream.ToArray());
    }

    /// <summary>
    /// Deserialize the object back into the object from an XML string
    /// </summary>
    /// <typeparam name="T">Type of the object to restore</typeparam>
    /// <param name="pXmlizedString">The string that represents the object in XML</param>
    /// <returns>A new instance of the restored object</returns>
    public static T DeserializeObject<T>(String pXmlizedString)
    {
        UTF8Encoding encoding = new UTF8Encoding();
        XmlSerializer xs = new XmlSerializer(typeof(T));
        MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(pXmlizedString));
        System.Xml.XmlTextWriter xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
        return (T)xs.Deserialize(memoryStream);
    } 
}







1 Answer, 1 is accepted

Sort by
0
Angel Petrov
Telerik team
answered on 18 Mar 2014, 02:25 PM
Hello Keith,

I have to say that the behavior experienced is expected and is caused by the fact that bind expressions are defined in the FormTemplate. Since a DataItem is not available for the insert item the expressions will fail. To resolve the problem I suggest populating the data for the edit items by subscribing to the OnItemDataBound event and removing the binding expressions from the markup.

C#:
protected void grdData_ItemDataBound(object sender, GridItemEventArgs e)
   {
       GridEditableItem editItem = e.Item as GridEditableItem;
       if (editItem != null && editItem.IsInEditMode)
       {
           UserData.User user = ((UserData.User)(editItem.DataItem));
           (editItem.FindControl("fldFirstName") as TextBox).Text = user.person.name;
           (editItem.FindControl("fldEMail") as TextBox).Text = user.person.email;
           (editItem.FindControl("cbxSalesRep") as CheckBox).Checked = user.salesRep;
       }
   }

Regards,
Angel Petrov
Telerik
 

DevCraft Q1'14 is here! Watch the online conference to see how this release solves your top-5 .NET challenges. Watch on demand now.

 
Tags
Grid
Asked by
Keith
Top achievements
Rank 1
Answers by
Angel Petrov
Telerik team
Share this question
or