How do you programmatically bind a gridview with a generic list?

I have the following code, I'm trying to get the bound the fields in the for each but it gets to the databind at the end I get an error.

"A field or property with the name 'Smith' was not found on the selected data source."

Code HTML4Strict:
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" EmptyDataText="No Data">
        <Columns>
        </Columns>
</asp:GridView>

Code Csharp:
if (!IsPostBack)
        {
            List<names> ln = new List<names>();
            dbconnect n = new dbconnect();
 
            ln = n.ReadDataNames();
 
            BoundField fname = new BoundField();
            fname.HeaderText="First Name";
 
            BoundField lname = new BoundField();
            lname.HeaderText = "Last Name";
 
            foreach(names nm in ln)
            {
                fname.DataField = nm.firstName;
                lname.DataField = nm.lastName;  
 
            }
 
            gv.Columns.Add(fname);
            gv.Columns.Add(lname);
 
            gv.DataSource = ln;
            gv.DataBind();
        }