6

ここ数日検索に費やした後、私は公式に立ち往生しています。オブジェクトをTelerikMVC3グリッドにバインドする作業をしていますが、キャッチは、動的に作成された列(自動生成ではない)が必要なことです。3つの列は既知であり、他の列は不明であり、これは注意が必要な部分です。基本的に、次の例のようになります。

KnowColumn1 | KnowColumn2 | UnknownColumn1 | 既知の列3既知の列1| KnowColumn2 | UnknownColumn1 | UnknownColumn2 | UnknownColumn3 | KnowColumn3など。

不明な列をリストに入れているので(列名を取得できるように辞書も試しました)、これはバインド時に複雑なことをします。私のコードは以下の通りです:

モデル(0から数百の行が存在する可能性がありますが、このモデルはタイプListのビューモデルにあり、動的に追加される0から20以上の列が存在する可能性もあります)

public class VendorPaymentsGLAccount
{
    public string GeneralLedgerAccountNumber { get; set; }
    public string GeneralLedgerAccountName { get; set; }
    public string DisplayName { get { return string.Format("{0} - {1}", GeneralLedgerAccountNumber, GeneralLedgerAccountName); } }
    public Dictionary<string, double> MonthAmount { get; set; }
    public double Total { get { return MonthAmount.Sum(x => x.Value); } }
    public List<string> Columns { get; set; }
    public List<double> Amounts { get; set; }

    public VendorPaymentsGLAccount() { }
}

ビュー(コメントアウトされたセクションは辞書を使おうとしていました)

<fieldset>
    <legend>General Ledger Account Spend History</legend>
    @if (Model.VendorPaymentsGLAccounts != null)
    {

            <br />
            @(Html.Telerik().Grid(Model.VendorPaymentsGLAccounts)
                    .Name("Grid")
                    .Columns(columns =>
                    {
                        columns.Bound(gl => gl.DisplayName).Title("General Ledger Account").Width(200).Filterable(false).Sortable(false);

                        //foreach (var month in Model.VendorPaymentsGLAccounts[0].MonthAmount)
                        //{
                        //    //columns.Bound(gl => gl.MonthAmount[month.Key.ToString()].ToString()).Title(month.Key.ToString()).Width(100).Filterable(false).Sortable(false);
                        //    //columns.Template(v => Html.ActionLink(v.VoucherID, "VoucherSummary", new { id = v.VoucherID, bu = v.BusinessUnitID, dtt = v.InvoiceDate.Ticks })).Title("Voucher").Width(100);
                        //    columns.Template(gl => Html.ActionLink(gl.MonthAmount[month.Key.ToString()].ToString(), "VoucherSummary")).Title(month.Key.ToString()).Width(100);
                        //}

                        for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
                        {
                            string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
                            columns.Template(gl => gl.Amounts[i - 1]).Title(colTemp).Width(100);
                        }

                        columns.Template(gl => String.Format("{0:C}", gl.Total)).Title("Total");
                    })
                    .Sortable()
                    .Pageable()
                    .Filterable()
                    .Footer(true))
    }
    else
    {
        <br />
        @:There are no records that match your selected criteria.
    }
</fieldset>

辞書アプローチを使用すると、正しいヘッダーテキストで列を正しく生成できましたが、列の値(私のテストでは2列しかありませんでした)は同じでした。誰かがこれを手伝うことができますか?これは奇妙な問題のようです。これを正しく行う方法を理解しようとしているだけです。

更新:これは、問題を示す辞書アプローチを使用したスクリーンショットです。列見出しは正しいですが、値は両方の動的列で同じです。

問題のスクリーンショット

4

5 に答える 5

7

Telerikグリッドコントロールで動的に定義された列を使用するのは難しい場合があります。しかし、あなたの場合、それは主に閉鎖の典型的な落とし穴です。

次のループでは、コンパイラはの各インスタンスをgl => gl.Amounts[i - 1]変数にバインドし、i後で評価します。

for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
{
  string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
  columns.Template(gl => gl.Amounts[i - 1]).Title(colTemp).Width(100);
}

実際、ループが終了した後に評価されます。したがってi、ループの完了につながる値が常にあります。

修正は一時変数を使用することです:

for (int i = 1; i <= (Model.VendorPaymentsGLAccounts[0].Columns.Count() - 1); i++)
{
  string colTemp = Model.VendorPaymentsGLAccounts[0].Columns[i - 1];
  int columnIndex = i - 1;
  columns.Template(gl => gl.Amounts[columnIndex]).Title(colTemp).Width(100);
}
于 2012-07-13T17:10:59.403 に答える
2

私も同じ問題を抱えていて、何時間もグーグルで検索していて、さまざまな支援ラインから多くの試みをしました。しかし、それでも、解決するのはそれほど簡単ではありませんでした!

そのため、ここで別の実用的な例を示すために、ソリューションも提供します。

情報:IListモデルを使用している私の場所でのみ機能します。他のコレクションも問題を引き起こしていました!

@model IList<CBS.Web.Models.Equipment.EquipmentViewModel>
@(Html.Telerik().Grid(Model)
    .Name("Grid")

    .DataKeys(keys =>
    {
        keys.Add(m => m.ID);
    })

    .DataBinding(dataBinding =>
    {
        dataBinding.Ajax()
            // renders the grid initially
            .Select("EquipmentGrid", "Equipment");
    })                    

    .Columns(columns =>
    {
        // Equipment IDs
        columns.Bound(m => m.ID).Hidden(true);
        columns.Bound(m => m.Name).Title("Equipments").Width(200);

        // Every item (EquipmentViewModel) of the Model has the same Count of Fields
        for (int i = 0; i < (Model[0].Fields.Count()); i++)
        {
            // Name of the column is everytime same as in Model[0]
            string columnName = Model[0].Fields.ElementAt(i).FieldDefinition.Name;
            // Constructs i-counted columns, dynamically on how much
            // Fields are owned by an Equipment. But note, that all Equipment-items
            // in the Model must have the same Count and disposal of Fields! 
            columns.Template(m => m.Fields
                                    .Where(f => f.FieldDefinition.Name == columnName)
                                    .Where(f => f.EquipmentId == m.ID).First().Value)
                                    .Title(columnName)
                                    .Width(columnName.Length * 8); // * 8 was the optimal lenght per character
        }
    })

    .ClientEvents(events => events.OnRowSelect("onRowSelected"))

    .Selectable()
    .Resizable(resizing => resizing.Columns(true))
    .Pageable()
    .Scrollable()
    .Groupable()
    .Filterable()
)

コントローラ:

public ActionResult EquipmentGrid(Guid id)
{            
    var belongingEquipments = _equipmentRepository.GetNotDeleted()
                                .OrderBy(e => e.Name).ToList()
                                .Where(e => e.RevisionId == id);

    List<EquipmentViewModel> equVMList = new List<EquipmentViewModel>();

    for (int i = 0; i < belongingEquipments.Count(); i++)
    {
        var equVM = new EquipmentViewModel
        {
            ID = belongingEquipments.ElementAt(i).ID,
            Name = belongingEquipments.ElementAt(i).Name,
            RevisionId = belongingEquipments.ElementAt(i).RevisionId,
            EquipmentTypeId = belongingEquipments.ElementAt(i).EquipmentTypeId,

            Fields = SortFields(belongingEquipments.ElementAt(i).Fields.ToList())
        };
        equVMList.Add(equVM);
    }

    return PartialView("EquipmentGrid", equVMList);
}

モデル:

namespace CBS.Web.Models.Equipment
{
    public class EquipmentViewModel
    {
        public Guid ID { get; set; }
        public string Name { get; set; }

        public Guid RevisionId { get; set; }                            
        public Guid EquipmentTypeId { get; set; }

        public virtual ICollection<FieldEntity> Fields { get; set; }
    }
}

FieldDefinition

namespace CBS.DataAccess.Entities
{
    public class FieldDefinitionEntity : EntityBase
    {
        [Required]
        public virtual Guid EquipmentTypeId { get; set; }
        public virtual EquipmentTypeEntity EquipmentType { get; set; }

        [Required(AllowEmptyStrings = false)]
        public virtual string Name { get; set; }

        public virtual int Numbering { get; set; }

        [Required]
        public virtual Guid TypeInformationId { get; set; }
        public virtual TypeInformationEntity TypeInformation { get; set; }

        public virtual ICollection<FieldEntity> Fields { get; set; }
    }
}

分野

namespace CBS.DataAccess.Entities
{
    public class FieldEntity : EntityBase
    {
        [Required]
        public virtual Guid EquipmentId { get; set; }
        public virtual EquipmentEntity Equipment { get; set; }

        [Required]
        public virtual Guid FieldDefinitionId { get; set; }
        public virtual FieldDefinitionEntity FieldDefinition { get; set; }

        public virtual string Value { get; set; }
    }
}
于 2012-09-07T22:12:21.413 に答える
2

実行時にリフレクションを使用して列を動的にバインドします。

@model IEnumerable<object>
@using System.Collections
@using System.Collections.Generic
@using System.Reflection;

@(Html.Telerik().Grid(Model)
    .Name("Grid")
    .Columns(columns =>                    
        {
            Type t = Model.GetType().GetGenericArguments()[0];
            foreach (var prop in t.GetProperties())
            {
                if (IsCoreType(prop.PropertyType))
                {
                    columns.Bound(prop.PropertyType, prop.Name);
                }
            }
        })    
        .DataBinding(binding => binding.Ajax()                                        
            .Select("SelectMethod", "SomeController")                                    
        )    
    .Sortable()    
    .Pageable()
    .Filterable()
    .Groupable()
)

@functions{
    public bool IsCoreType(Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            return IsCoreType(type.GetGenericArguments()[0]);
        }
        return !(type != typeof(object) && Type.GetTypeCode(type) == TypeCode.Object);
    }
}
于 2012-11-21T19:02:58.920 に答える
1

回避策は次のとおりです。

@(Html.Telerik().Grid(Model.Users)
    .Name("Grid")
    .Columns(columns => {
        columns.GenerateCustomColumns(columnSettings);          
       }).DataBinding(dataBinding => dataBinding.Ajax().Select("_getusers", "home"))
           .Scrollable(scrolling => scrolling.Enabled(true).Height("auto"))
           .Pageable(paging => paging.Enabled(true)
           .PageSize(10, new int[] { 5, 10, 20, 50, 100, 500 })
           .Position(GridPagerPosition.Both)
           .Total(Model.Users.Count)
           .Style(GridPagerStyles.PageSizeDropDown | GridPagerStyles.NextPreviousAndNumeric)
                           .PageTo(1))
           .Filterable(filtering => filtering.Enabled(true))
           .Reorderable(reordering => reordering.Columns(true))
               .NoRecordsTemplate(" ")
           .EnableCustomBinding(true)

)。

//列を動的に生成する拡張メソッド

public static class TelerikMvcGridColumnHelper
{
    public static void GenerateCustomColumns<T>(this GridColumnFactory<T>   columns,List<GridCustomColumnSettings> settings) where T:class
    {
        if (settings != null)
        {
            settings.ForEach(column =>
            {
                var boundedColumn = columns.Bound(column.Member);
                if (column.ClientFooterTemplate != null)
                    boundedColumn.ClientFooterTemplate(column.ClientFooterTemplate);

                if (!string.IsNullOrEmpty(column.Width))
                    boundedColumn.Width(column.Width);

            });
        }

    }
}

//列設定クラス

public class GridCustomColumnSettings : GridColumnSettings
 {
    public string ClientFooterTemplate { get; set; }

 }
于 2012-12-18T07:25:49.630 に答える
0

私はこの簡単な方法で行いました。注:次のソリューションは、ajax編集モードでも機能します(読み取り専用グリッドだけではありません):

ViewModelsが次の場合:

public class PriceSheetEditGridViewModel
{
    public IEnumerable<PriceSheetRowViewModel> Rows { get; set; }
    public IEnumerable<PriceSheetColumnViewModel> Columns { get; set; }
}

public class PriceSheetColumnViewModel {public int Id {get; セットする; } public string Title {get; セットする; }}

public class PriceSheetRowViewModel 
    {

        public int RowNo { get; set; }
        public string Description { get; set; }
        public double?[] Prices { get; set; }

    }

ビューは次のようになります(view.cshtmlファイルの一部...):

    ....
@model PriceSheetEditGridViewModel
...
                columns.Bound(o => o.Description ).Width(150);

                int i = 0;
                foreach (var col in Model.Columns)


{
                columns
                    .Bound(model => model.Prices).EditorTemplateName("PriceSheetCellPrice").EditorViewData(new { ColumnId = i })
                    .ClientTemplate("<span><#=Prices ? jsHelper.addCommas(Prices[" + i.ToString() + "]):null#></span>")
                    .Title(col.Title).Width(80);
                i++;
            }    

....

およびPriceSheetCellPrice.cshtmlエディターテンプレートファイル(shared \ editortemplatesフォルダー内):

  @model decimal?
@(Html.Telerik().NumericTextBox()
        .Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)+"["+ViewBag.ColumnId+"]")
                    .InputHtmlAttributes(new { style = "width:100%" })
})
        .EmptyMessage("")
        .DecimalDigits(0)
        .DecimalSeparator(",")
        .MinValue(0)
        .Value((double?) Model)
)
于 2013-03-13T05:59:45.040 に答える