0

ASP.NET MVC 4 プロジェクト内で DevExpress コントロールを使用しています。

GridViewASP.NET MVCの拡張機能でバインドされていない列を使用しています。CustomUnboundColumnDataイベント ハンドラでは、常にe.GetListSourceFieldValuenull が返されます。

次に、このメソッドを呼び出す代わりに、モデルから直接値を取得しようとしました (メソッドの呼び出しのすぐ上にあるコメント行を参照してください)。 .

Visual Web Developer Express 2010 エディションで ASP.NET MVC 4 を使用しています。MVC v12.2.10.0 の DevExpress 拡張機能を使用しています。

私のOSは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そのため、aから POCOに切り替え、すべてのカルチャにバインドされていない列を使用しました。

親切に助けてください。

4

1 に答える 1

0

さて、この質問を投稿したのはわずか 2 時間ほど前ですが、この問題を 8 時間以上抱えており、この問題を解決するためにさまざまな方法を試してきました。

そして今、私がしたことの1つがこの問題を解決しました. ここにあります。

DevExpress GridViewExtensionfor ASP.NET MVC を私のようなカスタム POCO にバインドしていて、その POCO に任意の種類のコレクションであるメンバーが 1 つ以上ある場合は、コンストラクターでコレクションを表すこれらのプロパティを初期化する必要があります。あなたのPOCO。

たとえば、私の場合、モデルは のリストでStringTableRowStringTableRowPOCO でした。

StringTableRowクラスには、コレクションである という名前のプロパティがありましたStringValuesIList<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; }
    }
}
于 2013-09-18T14:18:33.390 に答える