【问题标题】:Retrieve value of complex object bound to gridview control检索绑定到gridview控件的复杂对象的值
【发布时间】:2011-10-12 02:34:30
【问题描述】:

gridview 控件使复杂对象的数据绑定变得相当容易。在我的场景中,gridview 控件绑定到一个 Customer 对象,该对象具有一些“平面”属性和一个复杂属性,该属性采用 Address 类型的对象。网格按预期显示数据。问题是我没有办法在后面的代码中访问 Address 属性的值。例如,将 DataKeyNames 集合设置为 DataKeyNames="Id, Address.Id" 会导致错误:

DataBinding:System.Data.Entity.DynamicProxies.Customer_95531162E60920A5C3C02043F6564873913B91785C856624301E8B6E89906BF6 不包含名为 Address.Id 的属性。

在后面的代码中访问 Address.Id 字段值的正确方法是什么?理想情况下,我想做这样的事情:

    protected void CustomerDetailsObjectDataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
    if (CustomersGridView.SelectedIndex < 0) return;        

    // Retrieving the Customer's id works:
    e.InputParameters["id"] = Convert.ToString(CustomersGridView.DataKeys[CustomersGridView.SelectedIndex].Value);        

    // Retrieving the Address id doesn work:
    e.InputParameters["id"] = Convert.ToString(CustomersGridView.DataKeys[CustomersGridView.SelectedIndex].Values["Address.Id"].ToString());        
}

这是asp代码:

<ContentTemplate>

        <asp:GridView ID="CustomersGridView" runat="server" AutoGenerateColumns="False" DataSourceID="CustomersObjectDataSource"
                      onselectedindexchanged="CustomersGridView_SelectedIndexChanged" DataKeyNames="Id,Address.Id" ondatabound="CustomersGridView_DataBound">
            <Columns>
                <asp:TemplateField HeaderText="Aktion">
                    <ItemTemplate>
                        <asp:LinkButton runat="server" ID="SelectCustomerButton" Text="Auswählen" CommandName="Select" /> <br/>                         
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText="Kunde" SortExpression="LastName" ItemStyle-VerticalAlign="Top" >
                    <ItemTemplate>
                        <asp:Label ID="NumberLabel" runat="server" Text='<%#"GpNr: " + Eval("Number")%>'></asp:Label><br/>
                        <asp:Label ID="SalutationLabel" runat="server" Text='<%#Eval("Salutation")%>'></asp:Label>
                        <asp:Label ID="TitleLabel" runat="server" Text='<%#Eval("Title")%>'></asp:Label>
                        <asp:Label ID="FirstNameLabel" runat="server" Text='<%#Eval("FirstName")%>'></asp:Label>
                        <asp:Label ID="LastNameLabel" runat="server" Text='<%#Eval("LastName")%>'></asp:Label><br/>
                        <asp:Label ID="NameContactPersonLabel" runat="server" Text='<%#"Kontakt: " + Eval("NameContactPerson")%>'></asp:Label>
                    </ItemTemplate>
                    <ItemStyle VerticalAlign="Top" />
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Adresse" SortExpression="Address.PostalCode" ItemStyle-VerticalAlign="Top" >
                    <ItemTemplate>                            
                        <asp:Label ID="AddressIdLabel" runat="server" Text = '<%#Eval("Address.Id") %>'></asp:Label>
                        <asp:Label ID="AddressStreetLabel" runat="server" Text='<%#Eval("Address.Street")%>'></asp:Label>
                        <asp:Label ID="AddressHouseNumberLabel" runat="server" Text='<%#Eval("Address.HouseNumber")%>'></asp:Label>
                        <asp:Label ID="AddressHouseNumberExtensionLabel" runat="server" Text='<%#Eval("Address.HouseNumberExtension")%>'></asp:Label>
                        <asp:Label ID="AddressDoorNumberLabel" runat="server" Text='<%#Eval("Address.DoorNumber")%>'></asp:Label><br/>
                        <asp:Label ID="AddressPostalCodeLabel" runat="server" Text='<%#Eval("Address.PostalCode")%>'></asp:Label>
                        <asp:Label ID="AddressCityLabel" runat="server" Text='<%#Eval("Address.City")%>'></asp:Label><br/>
                        <asp:Label ID="AddressCountryLabel" runat="server" Text='<%#Eval("Address.Country")%>'></asp:Label>
                    </ItemTemplate>

谢谢!!

【问题讨论】:

  • 为什么不试试索引而不是实际的键值——CustomersGridView.DataKeys[CustomersGridView.SelectedIndex].Values[1]

标签: asp.net gridview nested-class datakey


【解决方案1】:

原因是Gridview将datakeynames作为属性名,它在CreateChildControls()过程中使用DataBinder.GetPropertyValue()来获取数据键值,而DataBinder.Eval支持多级属性(只要用点字符分隔即可)

例子:

object item = ...
DataBinder.Eval(item, "Address.Id"); //no problem
DataBinder.GetPropertyValue(item, "Address.Id"); //will throw exception

有几种解决方案可以解决您的问题:

  1. 派生您的自定义网格视图(覆盖 CreateChildControls()),它的 datakeynames 支持多层表达式。您可以使用 Reflector 来引用默认实现。 (大量工作)
  2. 在 RowDataBound 事件期间将复杂的属性值存储到视图状态中(首选,我也使用过 :))

例子:

private void CustomersGridView_RowDataBound(object sender, EventArgs args)
{
    if(e.Row.RowType = DataControlRowType.DataRow)
    {
        object id = DataBinder.Eval(e.Row.DataItem, "Id");

        //DictionaryInViewState is a variable that will be stored into viewstate later
        DictionaryInViewState[id] = DataBinder.Eval(e.Row.DataItem, "Address.Id");
    }
}

参考资料:

http://www.telerik.com/forums/problem-with-a-complex-datakeynames-value

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多