e.GetListSourceFieldValue在CustomUnboundColumnData事

2019-11-02 11:52发布

我使用的是ASP.NET MVC 4项目中的DevExpress控制。

我使用的未绑定列GridView扩展ASP.NET MVC。 在CustomUnboundColumnData事件处理程序,该e.GetListSourceFieldValue始终返回null我。

然后,我尝试直接从模型中所获得的价值,而不是调用此方法(请参阅只是调用方法上面的注释行),但即使奏效,它有副作用,我不会进入刚才。

我使用ASP.NET MVC 4 Visual Web Developer速成2010年版。 我使用的DevExpress扩展MVC v12.2.10.0。

我的操作系统是Windows 7中,64位。 不过,我使用的扩展名是只有32位。

因为它被分解成多个项目,其中大部分有很多的,我为我的客户写的IP代码,我不能船舶我的整体解决方案。 但这里是从我的代码中的相关部分。

Index.cshtml(Razor视图引擎)------------------------------------------ -------------------------

@model List<GlobalizationUI.Presentation.ViewModels.StringTableRow>

@{
    ViewBag.Title = "Strings";
}

<div id = "pageCaption">Strings</div>

@Html.Partial("_StringsPartial", Model)

_StringsPartial.cshtml(Razor视图引擎)------------------------------------------ -------------------------

@using System.Web.UI.WebControls;
@using System.Data;
@model List<GlobalizationUI.Presentation.ViewModels.StringTableRow>

@Html.DevExpress().GridView(settings =>
    {
        settings.Name = "gvStrings";

        settings.CallbackRouteValues = new { Controller = "Strings", Action = "StringsPartial" };

        settings.Width = 1200;

        settings.SettingsPager.Position = PagerPosition.TopAndBottom;
        settings.SettingsPager.FirstPageButton.Visible = true;
        settings.SettingsPager.LastPageButton.Visible = true;
        settings.SettingsPager.PageSizeItemSettings.Visible = true;
        settings.SettingsPager.PageSizeItemSettings.Items = new string[] { "10", "20", "50", "100", "200" };
        settings.SettingsPager.PageSize = 50;

        settings.Settings.ShowFilterRow = true;
        settings.Settings.ShowFilterRowMenu = true;

        settings.CommandColumn.Visible = true;
        settings.CommandColumn.ClearFilterButton.Visible = true;

        settings.Settings.ShowHeaderFilterButton = true;

        settings.KeyFieldName = "ResourceKeyId";

        settings.Columns.Add("Key");

        var categoryColumn = settings.Columns.Add("CategoryId", "Category");
        categoryColumn.ColumnType = MVCxGridViewColumnType.ComboBox;
        var categoryColumnEditProperties = categoryColumn.PropertiesEdit as ComboBoxProperties;
        categoryColumnEditProperties.DataSource = ViewBag.AllCategories;
        categoryColumnEditProperties.TextField = "Name";
        categoryColumnEditProperties.ValueField = "Id";
        categoryColumnEditProperties.ValueType = typeof(long);

        if (Model != null && Model.Count > 0 &&
            Model[0] != null && Model[0].StringValues != null && Model[0].StringValues.Count > 0)
        {
            foreach (var kvp in Model[0].StringValues)
            {
                settings.Columns.Add(col =>
                {
                    col.FieldName = kvp.CultureShortName;
                    col.Caption = kvp.CultureShortName;
                    col.UnboundType = DevExpress.Data.UnboundColumnType.Object;
                    col.SetDataItemTemplateContent(container => { ViewContext.Writer.Write(DataBinder.Eval(container.DataItem, col.FieldName + ".StringValue")); });

                    col.SetEditItemTemplateContent(container =>
                        {
                            Html.DevExpress().TextBox(s =>
                                {
                                    s.Name = string.Format("txt{0}", kvp.CultureShortName);
                                }).Bind(kvp.StringValue).Render();
                        });
                });
            }
        }

        settings.CustomUnboundColumnData = (sender, e) =>
        {
            var fixedColumns = new List<string> { "ResourceKeyId", "Key", "CategoryId" };

            if (!fixedColumns.Contains(e.Column.FieldName))
            {
                if (e.IsGetData)
                {
                    try
                    {
                        // var values = Model[e.ListSourceRowIndex].StringValues;

                        var values = e.GetListSourceFieldValue(e.ListSourceRowIndex, "StringValues") as IList<GlobalizationUI.Presentation.ViewModels.CultureNameAndStringValue>;

                        if (values != null)
                        {
                            var value = values.FirstOrDefault(pair => pair.CultureShortName == e.Column.FieldName);

                            var defaultValue = default(GlobalizationUI.Presentation.ViewModels.CultureNameAndStringValue);

                            e.Value = value.Equals(defaultValue) ? defaultValue : new GlobalizationUI.Presentation.ViewModels.CultureNameAndStringValue();
                        }
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debugger.Break();
                        System.Diagnostics.Debug.Print(ex.ToString());
                    }
                }
            }
        };

        foreach (GridViewDataColumn column in settings.Columns)
        {
            column.Settings.HeaderFilterMode = HeaderFilterMode.CheckedList;
        }

        settings.SettingsEditing.AddNewRowRouteValues = new { Controller = "Strings", Action = "CreateNew" };
        settings.SettingsEditing.UpdateRowRouteValues = new { Controller = "Strings", Action = "Edit" };
        settings.SettingsEditing.DeleteRowRouteValues = new { Controller = "Strings", Action = "Delete" };

        settings.SettingsEditing.Mode = GridViewEditingMode.Inline;

        settings.SettingsBehavior.ConfirmDelete = true;

        settings.CommandColumn.Visible = true;
        settings.CommandColumn.NewButton.Visible = true;
        settings.CommandColumn.EditButton.Visible = true;
        settings.CommandColumn.UpdateButton.Visible = true;
        settings.CommandColumn.DeleteButton.Visible = true;

    }).Bind(Model).GetHtml()

StringsController ------------------------------------------------- ------------------

using System.Data;
using System.Web.Mvc;
using GlobalizationUI.BusinessObjects;
using Resources.BaseServices.Caching;
using System.Collections.Generic;
using System.ComponentModel;
using GlobalizationUI.Presentation.ViewModels;
using Resources.Util;

namespace GlobalizationUI.Presentation.Controllers
{
    public class StringsController : Controller
    {
        private static string CacheKey_StringTable = "CacheKey_StringTable";
        private static string CacheKey_AllCategories = "CacheKey_AllCategories";
        private static object padLock = new object();

        public ActionResult Index()
        {
            var stringTable = GetStringTable();

            ViewBag.AllCategories = GetCategoryList();

            return View(stringTable);
        }

        public ActionResult StringsPartial()
        {
            var stringTable = GetStringTable();

            ViewBag.AllCategories = GetCategoryList();

            return PartialView("_StringsPartial", stringTable);
        }

        [HttpPost]
        public ActionResult CreateNew(StringTableRow row)
        {
            System.Diagnostics.Debugger.Break();

            foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(row))
            {
                System.Diagnostics.Debug.Print(prop.Name);
            }

            return Content("Hello, there!");
        }

        [HttpPost]
        public ActionResult Edit(DataRow row)
        {
            return new EmptyResult();
        }

        [HttpPost]
        public ActionResult Delete(long resourceKeyId)
        {
            return new EmptyResult();
        }

        private IEnumerable<Category> GetCategoryList()
        {
            lock (padLock)
            {
                if (CacheManager.Contains(CacheKey_AllCategories))
                {
                    return CacheManager.Get<IEnumerable<Category>>(CacheKey_AllCategories);
                }
            }

            var list = Category.All;

            lock (padLock)
            {
                CacheManager.Add(CacheKey_AllCategories, list);
            }

            return list;
        }

        private List<StringTableRow> GetStringTable()
        {
            List<StringTableRow> stringTable;

            lock (padLock)
            {
                if (CacheManager.Contains(CacheKey_StringTable))
                {
                    return CacheManager.Get<List<StringTableRow>>(CacheKey_StringTable);
                }
            }

            stringTable = new StringTable().ToListOfStringTableRows();

            lock (padLock)
            {
                CacheManager.Add(CacheKey_StringTable, stringTable);
            }

            return stringTable;
        }
    }
}

视图模型------------------------------------------------ -------------------

using System.Collections.Generic;

namespace GlobalizationUI.Presentation.ViewModels
{
    public class StringTableRow
    {
        public long ResourceKeyId { get; set; }

        public string Key { get; set; }

        public long CategoryId { get; set; }

        public List<CultureNameAndStringValue> StringValues { get; set; }
    }
}

namespace GlobalizationUI.Presentation.ViewModels
{
    public class CultureNameAndStringValue
    {
        public CultureNameAndStringValue() : this(null, null) { }

        public CultureNameAndStringValue(string cultureShortName, string stringValue)
        {
            CultureShortName = cultureShortName;

            StringValue = stringValue;
        }

        public string CultureShortName { get; set; }

        public string StringValue { get; set; }
    }
}

型号:------------------------------------------------ -------------------

using System.Data;
using GlobalizationUI.Data;

namespace GlobalizationUI.BusinessObjects
{
    public class StringTable : DataTable
    {
        public StringTable()
        {
            var sql = @"
            declare @stmt nvarchar(max)

            select @stmt =
                isnull(@stmt + ', ', '') +
                'max(case when s.CultureId = ' + cast(c.Id as nvarchar(max)) +
                ' then s.ResourceValue end) as ' + quotename(c.ShortName)
            from Culture as c
            where c.Supported = 1

            select @stmt = '
                select
                    rk.Id AS ResourceKeyId,
                    rk.Name AS [Key],
                    c.Id AS CategoryId,
                    c.Name as CategoryName, ' + @stmt + '
                from StringCategory as sc
                    LEFT OUTER join Category as c on c.Id = sc.CategoryId
                    RIGHT OUTER JOIN ResourceKey as rk on rk.Id = sc.ResourceKeyId
                    inner join Strings as s on s.ResourceKeyId = rk.Id
                group by rk.Id, rk.Name, c.Id, c.Name
                '

            exec sp_executesql @stmt = @stmt;";

            this.Merge(Database.DefaultDatabase.GetDataTable(sql));
        }
    }
}

模型视图模型转换:-------------------------------------------- -----------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlTypes;

namespace GlobalizationUI.Presentation.ViewModels
{
    public static class DataTableExtensions
    {
        public static List<StringTableRow> ToListOfStringTableRows(this DataTable dataTable)
        {
            var ret = new List<StringTableRow>();

            if (dataTable == null || dataTable.Rows.Count == 0) return ret;

            foreach (DataRow row in dataTable.Rows)
            {
                StringTableRow stringTableRow = new StringTableRow();

                foreach (DataColumn column in dataTable.Columns)
                {
                    if (string.Compare(column.ColumnName, "ResourceKeyId", true) == 0)
                    {
                        stringTableRow.ResourceKeyId = (long)row[column.ColumnName];
                    }
                    else if (string.Compare(column.ColumnName, "Key", true) == 0)
                    {
                        stringTableRow.Key = (string)row[column.ColumnName];
                    }
                    else if (string.Compare(column.ColumnName, "CategoryId", true) == 0)
                    {
                        var categoryId = row[column.ColumnName];

                        stringTableRow.CategoryId = categoryId == DBNull.Value ? 0 : (long)categoryId;
                    }
                    else if (string.Compare(column.ColumnName, "CategoryName", true) == 0)
                    {
                        continue;
                    }
                    else
                    {
                        if (stringTableRow.StringValues == null)
                            stringTableRow.StringValues = new List<CultureNameAndStringValue>();

                        stringTableRow.StringValues.Add(new CultureNameAndStringValue(column.ColumnName, (string)row[column.ColumnName]));
                    }
                }

                ret.Add(stringTableRow);
            }

            return ret;
        }
    }
}

所述用户接口被假定稍微看起来像上面显示的图片。 根据由特定的安​​装/部署/业务客户端支持文化数目由SQL查询返回的列数是可变的。 因此,需要使用未绑定列。

这张照片我是不是通过这个代码,而是通过一个旧版本的我的代码时,我直接数据绑定到一个System.Data.DataTable ,并没有使用任何未绑定列。 这一切都很好,直到我在在MVC /服务器端的操作编辑数据。 所以,我从使用开关DataTable到POCO和使用未绑定列所有文化。

请帮助。

Answer 1:

好吧,虽然我只有2个小时左右前张贴了这个问题,我现在已经有这样的麻烦超过8小时,并已尝试各种方法来解决这个问题。

就在刚才,我没做这个问题的事情之一走开。 这里是。

如果您结合您的DevExpress GridViewExtension为ASP.NET MVC到自定义POCO喜欢我的,POCO有一个或多个成员是任何类型的集合,那么,你必须 绝对必须初始化那些代表在构造函数集合的属性你的POCO。

对于例如,在我的情况,该模型的列表StringTableRow “s,其中StringTableRow是POCO。

StringTableRow类,我有一个属性命名StringValues这是类型IList<CultureNameAndStringValue>这是一个集合。 因此,我的代码工作,我初始化StringValues财产在我的构建StringTableRow阶级和一切开始工作。

using System.Collections.Generic;

namespace GlobalizationUI.Presentation.ViewModels
{
    public class StringTableRow
    {
        public StringTableRow()
        {
            // I added this ctor and initialized the
            // StringValues property and the broken
            // custom binding to unbound columns started
            // to work.
            StringValues = new List<CultureNameAndStringValue>();
        }

        public long ResourceKeyId { get; set; }

        public string Key { get; set; }

        public long CategoryId { get; set; }

        public IList<CultureNameAndStringValue> StringValues { get; set; }
    }
}


文章来源: e.GetListSourceFieldValue returns null in the CustomUnboundColumnData event handler