1

更新:私はまだ何も理解していません。それは確かにそれがそうであるように働くべきであるように思われます。

ビューモデルにバインドしたテレリックグリッドがあります。グリッドには基本的に、Vehicleオブジェクトの名前とタイプが表示されます。データキーに、VehicleIDフィールドとTimestampフィールドの両方を追加しました。グリッドがajax更新を投稿する場合、Timestampフィールドはnullです。

ビューに渡されるときに、ビューモデルのタイムスタンプフィールドに値があることを確認しました。

関連するコードは次のとおりです。

意見:

...
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
    columns.Bound(o => o.VehicleID).Visible(false);        
    columns.Bound(o => o.VehicleName);
    columns.Bound(o => o.VehicleType);
})
.DataBinding(dataBinding =>
    {
        dataBinding.Server().Select("Index", "Vehicle");
        dataBinding.Ajax().Select("_Index", "Vehicle").Enabled(true);
        dataBinding.Ajax().Update("_SaveVehicle", "Vehicle");
        dataBinding.Ajax().Delete("_DeleteVehicle", "Vehicle");
    })
    .Scrollable(scrolling => scrolling.Enabled(true))
    .Sortable(sorting => sorting.Enabled(true))
    .Pageable(paging => 
        paging.Enabled(true)
        .PageSize(20)
        .Position(GridPagerPosition.Bottom))
    .Filterable(filtering => filtering.Enabled(true))
    .Groupable(grouping => grouping.Enabled(true))
    .Footer(true)
    .ToolBar(toolbar => toolbar.Template(
        @<text>
            @using (Html.BeginForm("ExportCsv", "Vehicle", FormMethod.Post, new {id = "export"}))
            {
                <text>
                    <input type="submit" value="Export to CSV" id="export" />
                </text>
            }

            <label class="error">@ViewBag.AjaxErrorMessage</label>

        </text>
        ))            

    .Columns(columns =>
        {
            columns.Command(command =>
                {
                    command.Custom("details").Text("Details").Action("Edit", "Vehicle").HtmlAttributes(new { style = "text-align: center" }) ;
                    command.Edit().ButtonType(GridButtonType.Image);
                    command.Delete().ButtonType(GridButtonType.Image);
                }).Width(165);
        })
    .DataKeys(dataKeys => 
        {
            dataKeys.Add(key => key.Timestamp).RouteKey("Timestamp");
            dataKeys.Add(key => key.VehicleID).RouteKey("VehicleID"); 

        })
    .ClientEvents(events => events.OnEdit("onEdit"))
    .ColumnContextMenu()
    .Resizable(config =>
        {
            config.Columns(true);
        })
    .Reorderable(config =>
        {
            config.Columns(true);
        })

)

<script type = "text/javascript">
function onEdit(e) {
    $(e.form).find('#VehicleType').data('tDropDownList').select(function (dataItem) {
        return dataItem.Text == e.dataItem['vehicleType'];
    });
}
</script>

モデルの表示:

using System;
using System.ComponentModel.DataAnnotations;

namespace ShopLog.ViewModels
{
    public class VehicleIndexViewModel
    {

    //public IEnumerable<Vehicle> Vehicles { get; set; }
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid VehicleID { get; set; }

    [Timestamp]
    public Byte[] Timestamp { get; set; }

    [Required]
    [Display(Name = "Vehicle Name")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string VehicleName { get; set; }

    [Display(Name = "Fuel Type")]
    [StringLength(30, ErrorMessage = "\"{0}\" must be no more than {1} characters long.")]
    public string FuelType { get; set; }

    [Display(Name = "Notes")]
    [DataType(DataType.MultilineText)]
    public string Notes { get; set; }

    [UIHint("VehicleType")]
    [Display(Name = "Type")]
    public string VehicleType { get; set; }

    [Display(Name = "Transmission Type")]
    public String TransmissionType { get; set; }
    }
}

更新用のコントローラーの郵便番号 最初の行にブレークポイントを設定すると、VehicleIndexViewModelのタイムスタンププロパティがnullになります。フォームコレクションからタイムスタンプを取得しようとしましたが、そこでもnullです。

[AcceptVerbs(HttpVerbs.Post)]
    [GridAction]
    public ActionResult _SaveVehicle(VehicleIndexViewModel vehicleIndexViewModel, FormCollection formcollection)
    {          

        if (TryUpdateModel(vehicle))
        {
            try
            {
                //Delete the record
                db.Entry(vehicle).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                ViewBag.AjaxErrorMessage = "That record has been edited by someone else since you started editing it.";
            }
            catch (DataException)
            {
                ViewBag.AjaxErrorMessage = "Error saving data, please try again.";
            }
        }
        //Rebind the grid
        PopulateVehicleTypes();
        return View(new GridModel(GetIndexViewData()));
    }

ありがとう!

4

1 に答える 1

1

これが私が考え出したものです:

byte[] は ViewModel からうまく返されません。なんで?知らない。

ViewModel の "Timestamp" フィールドを byte[] ではなく文字列にすることになりました。Model から ViewModel にデータを渡すときは、「Convert.ToBase64String( value )」を呼び出します。ViewModel からモデルにデータを渡すときは、「Convert.FromBase64String( value )」を呼び出します。

モデル:

[Timestamp]
public Byte[] Timestamp { get; set; }

ビューモデル:

[Timestamp]
public string Timestamp {get; set;}

コントローラ:

    [AcceptVerbs(HttpVerbs.Post)]
    [GridAction]
    public ActionResult _SaveVehicle(VehicleIndexViewModel vehicleIndexViewModel)
    {
        Vehicle vehicle = Mapper.Map<VehicleIndexViewModel, Vehicle>(vehicleIndexViewModel);

        if (TryUpdateModel(vehicle))
        {
            try
            {
                //Delete the record
                db.Entry(vehicle).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                ViewBag.AjaxErrorMessage = "That record has been edited by someone else since you started editing it.";
            }
            catch (DataException)
            {
                ViewBag.AjaxErrorMessage = "Error saving data, please try again.";
            }
        }
        //Rebind the grid
        PopulateVehicleTypes();
        return View(new GridModel(GetIndexViewData()));
    }

Global.ascx の Automapper マッピング

AutoMapper.Mapper.CreateMap<ShopLog.Models.Vehicle, ShopLog.ViewModels.VehicleIndexViewModel>().ForMember(m => m.Timestamp, opt => opt.ResolveUsing<VehicleTimestampResolver>());
AutoMapper.Mapper.CreateMap<ShopLog.ViewModels.VehicleIndexViewModel, ShopLog.Models.Vehicle>().ForMember(m => m.Timestamp, opt => opt.ResolveUsing<VehicleIndexViewModelTimestampResolver>());

    public class VehicleTimestampResolver : AutoMapper.ValueResolver<Vehicle, string>
    {
        protected override string ResolveCore(Vehicle source)
        {
            return Convert.ToBase64String(source.Timestamp);
        }
    }

    public class VehicleIndexViewModelTimestampResolver : AutoMapper.ValueResolver<ShopLog.ViewModels.VehicleIndexViewModel, byte[]>
    {
        protected override byte[] ResolveCore(ShopLog.ViewModels.VehicleIndexViewModel source)
        {
            return Convert.FromBase64String(source.Timestamp);
        }
    }

表示: (データキーに注意)

@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
    columns.Bound(o => o.VehicleID).Visible(false);        
    columns.Bound(o => o.VehicleName);
    columns.Bound(o => o.VehicleType);
})    
.DataBinding(dataBinding =>
    {
        dataBinding.Server().Select("Index", "Vehicle");
        dataBinding.Ajax().Select("_Index", "Vehicle").Enabled(true);
        dataBinding.Ajax().Update("_SaveVehicle", "Vehicle");
        dataBinding.Ajax().Delete("_DeleteVehicle", "Vehicle");
    })
    .Scrollable(scrolling => scrolling.Enabled(true))
    .Sortable(sorting => sorting 
        .Enabled(true)
        .OrderBy(sortOrder => sortOrder.Add(o => o.VehicleName).Ascending())
        .SortMode(GridSortMode.MultipleColumn))
    .Pageable(paging => 
        paging.Enabled(true)
        .PageSize(20)
        .Position(GridPagerPosition.Bottom))
    .Filterable(filtering => filtering.Enabled(true))
    .Groupable(grouping => grouping.Enabled(true))
    .Footer(true)
    .ToolBar(commands => commands
        .Custom()
            .HtmlAttributes(new {id = "export"})
            .Text("Export to CSV")
                .Action("ExportCsv", "Vehicle", new { page = 1, orderBy = "~", filter = "~" }))                                                     
    .Columns(columns =>
        {
            columns.Command(command =>
                {
                    command.Custom("details").Text("Details").Action("Edit", "Vehicle").HtmlAttributes(new { style = "text-align: center" }) ;
                    command.Edit().ButtonType(GridButtonType.Image);
                    command.Delete().ButtonType(GridButtonType.Image);
                }).Width(165);
        })
    .DataKeys(dataKeys => 
        {
            dataKeys.Add(key => key.Timestamp).RouteKey("Timestamp");
            dataKeys.Add(key => key.VehicleID).RouteKey("VehicleID"); 

        })
    .ClientEvents(events => events 
        .OnEdit("onEdit")
        .OnDataBound("onDataBound"))
    .ColumnContextMenu()
    .Resizable(config =>
        {
            config.Columns(true);
        })
    .Reorderable(config =>
        {
            config.Columns(true);
        })        
)

あとは、"ViewBag.AjaxErrorMessage" がビューに返されたときにどこに表示するかを決めるだけですが、それほど難しいことではありません。:)

于 2012-04-12T21:15:25.440 に答える