我使用的是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和使用未绑定列所有文化。
请帮助。