【问题标题】:Clone reference type properties with CustomButtonCallback使用 CustomButtonCallback 克隆引用类型属性
【发布时间】:2015-02-11 14:03:46
【问题描述】:

我正在尝试关注the DevExpress documentation example on cloning rows。基础知识很容易掌握,但是当您尝试克隆值类型以外的属性时,事情就会变得棘手。

第一次尝试/设置复制:

我已将我的真实场景缩小到问题的一个小(ish)重现。以下是新创建的 ASP.NET 2.0 webforms 应用程序的全部内容。首先,假设这些域对象(这里也将兼作 DTO):

public class Qualification
{
    public long Id { get; set; }
    public string Title { get; set; }
}

public class Person
{
    public long Id { get; set; }
    public string Name { get; set; }
    public Qualification Qualification { get; set; }
}

然后有两个快速的'n脏数据源类,如下所示:

public class QualificationOds
{
    public static List<Qualification> Qualificiations = new List<Qualification>
    {
        new Qualification { Id = 1, Title = "Doctore" }
    };

    public List<Qualification> GetRecords()
    {
        return Qualificiations;
    }
}

public class PeopleOds
{
    public List<Person> GetRecords()
    {
        return new List<Person> 
        {
            new Person
            {
                Id = 1, 
                Name = "John Doe", 
                Qualification = QualificationOds.Qualificiations[0] 
            }
        };
    }
}

default.aspx 页面将首先将dx 注册到 DevExpress 命名空间:

<%@ Register Assembly="DevExpress.Web.ASPxGridView.v11.1, Version=11.1.11.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxGridView" TagPrefix="dx" %>
<%@ Register Assembly="DevExpress.Web.ASPxEditors.v11.1, Version=11.1.11.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web.ASPxEditors" TagPrefix="dx" %>

并有一个包含此代码的表单:

<asp:ObjectDataSource runat="server" ID="peopleDataSource" TypeName="DevxTest.PeopleOds" SelectMethod="GetRecords" />
<asp:ObjectDataSource runat="server" ID="qualificationsDataSource" TypeName="DevxTest.QualificationOds" SelectMethod="GetRecords" />

<dx:ASPxGridView 
    runat="server"
    id="grvPeople"
    KeyFieldName="Id"
    DataSourceID="peopleDataSource"
    OnCustomButtonCallback="grid_CustomButtonCallback"
    OnInitNewRow="grid_InitNewRow">
    <Columns>
        <dx:GridViewCommandColumn>
            <EditButton Visible="true" />
            <CustomButtons>
                <dx:GridViewCommandColumnCustomButton ID="Clone" Text="Clone" />
            </CustomButtons>
        </dx:GridViewCommandColumn>
        <dx:GridViewDataTextColumn FieldName="Name" />
        <dx:GridViewDataComboBoxColumn FieldName="Qualification.Id" >
            <PropertiesComboBox 
                DataSourceID="qualificationsDataSource"
                TextField="Title"
                ValueField="Id"
                ValueType="System.Int64" />
        </dx:GridViewDataComboBoxColumn>
    </Columns>
</dx:ASPxGridView>

后面的代码包含将一行克隆到一个新的编辑表单的代码,基于前面提到的 DevExpress 示例,如下所示:

private string[] fieldsToCopy = { "Name", "Id" };
private Hashtable valuesToClone;

protected void grid_CustomButtonCallback(object sender, ASPxGridViewCustomButtonCallbackEventArgs e)
{
    if (e.ButtonID != "Clone") return;

    valuesToClone = new Hashtable();

    foreach (var fieldName in fieldsToCopy)
    {
        valuesToClone[fieldName] = grvPeople.GetRowValues(e.VisibleIndex, fieldName);
    }

    grvPeople.AddNewRow();
}

protected void grid_InitNewRow(object sender, DevExpress.Web.Data.ASPxDataInitNewRowEventArgs e)
{
    if (valuesToClone == null) return;

    foreach (string fieldName in fieldsToCopy)
    {
        e.NewValues[fieldName] = valuesToClone[fieldName];
    }
}

这适用于Name 属性,但不适用于Qualification 属性。它在页面上显示如下:

我还尝试将"Qualification.Id""Qualification" 作为要复制的字段名称,但没有骰子。无论如何,我很确定它应该是 "Id",就像在我的示例中一样,因为调试器仅针对这种情况显示正确的 GetRowValues 返回值。

第二次尝试/自定义代码来处理下拉列表:

所以我想我需要一些自定义代码来设置下拉列表的 NewValue。首先,我为 Qualification 列创建一个 EditItemTemplate,如下所示:

<EditItemTemplate>
    <dx:ASPxComboBox 
        runat="server" 
        ID="qualificationCombo" 
        DataSourceID="qualificationsDataSource"
        TextField="Title"
        ValueField="Id"
        ValueType="System.Int64" />
</EditItemTemplate>

然后我将此代码添加到grid_InitNewRow:

// Attempt to set the combo box to a value:
var column = grvPeople.Columns["Qualification"] as GridViewDataColumn;
var comboBox = grvPeople.FindEditRowCellTemplateControl(column, "qualificationCombo") as ASPxComboBox;
var item = comboBox.Items.FindByValue(valuesToClone["Id"]);
item.Selected = true;

而且它有效!但是,现在不再克隆 Name。它看起来像这样:

我不知道为什么,但是添加的代码有一个副作用,导致NewValues setter 方法失败。

底线:

底线相当简单:如何将 DevExpress 示例更改为也可以克隆引用类型属性的示例?


PS。我也有cross-posted my question on the DevExpress support forum

【问题讨论】:

  • 网格中有两列:“名称”和“Qualification.Id”。在 grid_CustomButtonCallback 函数中复制值时,您将以下值作为第二个参数传递给 ASPxGridView.GetRowValues 方法:“Name”和“Id”。我想第二个值应该是“Qualification.Id”,而不是“Id”。
  • 感谢@Uranus,您的评论很到位。我已经尝试过了,但是在 EditItemTemplate 就位的情况下这样做了:那么它仍然无法正常工作。 DevExpress 支持基本上回答了相同的问题。我还找到了需要 EditItemTemplate 时的解决方案/解决方法,因此我将所有这些编译成下面的答案。

标签: asp.net webforms devexpress


【解决方案1】:

您提到"Qualification.Id" 不起作用,但您很可能在EditItemTemplate 存在时尝试过。如果没有这样的模板,那么该代码实际上可以工作。

要完整,请将fieldsToCopy 代码行更改为:

private string[] fieldsToCopy = { "Name", "Qualification.Id" };

并且确保没有EditItemTemplate,然后它就会起作用。

或者,如果您因某种原因被EditItemTemplate 卡住,有一个“解决方案”可以确保该模板中的 ComboBox 绑定到克隆值。确保使用以下代码连接到 ComboBox 上的 OnDataBound

protected void qualificationCombo_DataBound(object sender, EventArgs e)
{
    var column = grvPeople.Columns["Qualification"] as GridViewDataColumn;
    var comboBox = grvPeople.FindEditRowCellTemplateControl(column, "qualificationCombo") as ASPxComboBox;
    var item = comboBox.Items.FindByValue(valuesToClone["Id"]);
    item.Selected = true;
}

这将正确地将 ComboBox 设置为克隆值,同时还保留用于普通字段的 e.NewValues 方法不变。

【讨论】:

    猜你喜欢
    • 2014-01-09
    • 2010-11-23
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2018-03-26
    相关资源
    最近更新 更多