【问题标题】:Edit an object that as no key (Value object) in GridView (ASP.NET)在 GridView (ASP.NET) 中编辑一个没有键(值对象)的对象
【发布时间】:2016-06-03 10:40:52
【问题描述】:

我有我的主要对象Person 和一组Adrresses 值对象,如下所示:

public class Person
{
    public virtual int Id {get; set;}
    public virtual string Name {get; set;}
    private IList<Adrress > _adrresses= new List<Adrress>();
    public virtual IEnumerable Adrress Adrresses {...}

    public virtual void AddAddress(Address a){...}
    public virtual void RemoveAddress(Address a){...}
    public virtual void ChangeAddress(OldAddress oa, OldAddress oa)
    {
        int index = _adrresses.IndexOf(oa);
        if (index != -1)
            _adrresses[index] = oa;
    }
}

public class Adrress 
{
    public virtual string Street {get; set;}
    public virtual string Number {get; set;}
    public virtual string City {get; set;}
    ... other 7 fields
}

在我的 asp 页面中,我有一个 Gridview,用户可以在其中添加、删除或更改地址。

问题是:如何从网格中的一个用户选择中获取正确的地址? 我是否必须从网格中读取每个字段并使用它们来构造我必须搜索的地址?

我使用CommandArgument 传递 Container.DataItemIndex 所以我不能用它来发送整个对象到代码

编辑: 这是网格的摘录:

<asp:GridView ID="gvElencoFaseAttivita" runat="server" 
    AllowPaging="false" AutoGenerateColumns="False" 
    Width="100%" CssClass="datiGridView tabletwo" ShowHeader="False" 
    OnRowCommand="gvElencoFaseAttivita_RowCommand" 
    OnRowUpdating="gvElencoFaseAttivita_RowUpdating" 
    OnRowDeleted="gvElencoFaseAttivita_RowDeleted" 
    OnRowEditing="gvElencoFaseAttivita_RowEditing" 
    OnRowCancelingEdit="gvElencoFaseAttivita_RowCancelingEdit">
    <Columns>
        <asp:TemplateField HeaderText="Sel">
            <ItemTemplate>
                <asp:LinkButton ID="lbtnEditFaseAttivita" runat="server" CausesValidation="False" CommandName="Edit" CommandArgument='<%# Container.DataItemIndex %>' ToolTip="Modifica la fase" CssClass="imgModificaPiccola" />
            </ItemTemplate>
            <EditItemTemplate>
                <asp:LinkButton ID="lbtnAggiornaFaseAttivita" runat="server" ValidationGroup="UpdateFaseAttivitaGrid" CommandName="Update" CssClass="imgSalvaPiccola" ToolTip="Salva le modifiche" CommandArgument='<%# Container.DataItemIndex %>' />
            </EditItemTemplate>
            <ItemStyle CssClass="gestioneFaseAttivitaTd2" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Street" SortExpression="Street">
            <ItemTemplate>
                <asp:Label ID="lblStreet" runat="server" Text='<%# ((Adrress)Container.DataItem).Street %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtEditStreet" runat="server" Text='<%# ((Adrress)Container.DataItem).Street %>'></asp:TextBox>
            </EditItemTemplate>
            <ItemStyle CssClass="gestioneFaseAttivitaTd3" />
        </asp:TemplateField>
    </Columns>
    <SelectedRowStyle CssClass="selezioneGridView" />
    <AlternatingRowStyle CssClass="odd" />
</asp:GridView>

这就是dataBind

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

protected void loadGridAddress()
{
    using (iuow = kernel.Get<IUnitOfWork>())
    {
        gvElencoFaseAttivita.DataSource = person.Addresses;
        gvElencoFaseAttivita.DataBind();
    }
}

protected void gvElencoFaseAttivita_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    var a = e.OldValues[""];  //e.OldValues  here is empty
}

【问题讨论】:

  • 您可以在这篇文章中找到您需要的信息:stackoverflow.com/questions/36827111/…。
  • 它使用 DataKeyNames,同时我正在寻找一种方法来传递 Container.DataItem。我在 RowUpdating 中也有问题,因为 OldValues 和 newValues 是空的,因为我没有 ObjectDataSource(并且我只有在不是回发时才加载 gridview
  • 我需要查看将数据绑定到 GridView 的代码以了解其工作原理。也许还有 GridView 的标记。
  • 现在查看我编辑的问题

标签: c# asp.net gridview value-objects


【解决方案1】:

您可以定义一个方法来提供对象的字符串表示形式,以及接受相同表示形式的构造函数。由于您在评论中提到了 JSON,它可能是:

public class Address 
{
    public virtual string Street {get; set;}
    public virtual string Number {get; set;}
    public virtual string City {get; set;}
    ...

    public string ToJSON()
    { 
        // Encode the object as as JSON string
        ...
        return strJSON;
    }

    public Address(string json)
    {
        // Decode JSON string and set object properties
        ...
    }
}

您可以将该 JSON 字符串保存在隐藏字段中:

<EditItemTemplate>
    <asp:HiddenField ID="hfAddress" runat="server" Value='<%# ((Address)Container.DataItem).ToJSON() %>' />
    <asp:TextBox ID="txtEditStreet" runat="server" Text='<%# ((Address)Container.DataItem).Street %>'/>
    ...
</EditItemTemplate>

并在RowUpdating 事件处理程序中检索它以重新创建原始对象:

protected void gvElencoFaseAttivita_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    GridViewRow row = gvElencoFaseAttivita.Rows[e.RowIndex];
    HiddenField hfAddress = row.FindControl("hfAddress") as HiddenField;
    TextBox txtEditStreet = row.FindControl("txtEditStreet") as TextBox;
    Address oldAddress = new Address(hfAddress.Value);
    string newStreet = txtEditStreet.Text;
    ...
}

【讨论】:

  • 或直接不使用 eval 以避免将字段写入 aspx 中的字符串。我也在玩 Newtonsoft.Json.JsonConvert.SerializeObject((FaseAttivita)Container.DataItem 将整个对象保存为单个字符串
  • 您可以定义地址类的ObjectValue 字符串属性,该属性将包含对象的完整表示,并将该属性的值保存在 HiddenField 中。
  • 为什么不是 json?为什么我不能避免在字符串中编码属性名称?现在支持您的答案,如果编辑以避免“魔术字符串”,我会接受它。现在我必须回家,直到星期一才下班。现在谢谢
  • 可能是 JSON,是的。我更新了我的答案。抱歉,我理解您希望在标记中访问数据的方式有点慢。 (注意,在我的代码示例中,我写的是“地址”而不是“地址”。)
  • 通过以下修改完成: ic ascx 和 DeserializeObject 在后面的代码中
猜你喜欢
  • 2021-07-08
  • 1970-01-01
  • 2021-05-30
  • 2020-07-08
  • 2022-11-22
  • 2023-01-08
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多