您可以装饰您的enum MyEnum
with[Flags]
属性并将其项目的值设置为 2 的不同幂。例如,您的枚举可能如下所示:
[Flags]
public enum MyEnum
{
Enum1 = 1,
Enum2 = 2,
Enum3 = 4,
Enum4 = 8,
Enum5 = 16
}
现在,您MyEnumCheckBox
的类属性PartRecord
将是类型int
:
public virtual int MyEnumCheckBox { get; set; }
您可以在类内创建代理属性Part
。例如:
private IList<MyEnum> _myCheckBox;
[MyEnumSelector]
public IList<MyEnum> MyCheckBox
{
get
{
if (_myCheckBox == null)
{
_myCheckBox = new List<MyEnum>();
foreach (MyEnum item in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)Record.MyEnumCheckBox & item) == item)
_myCheckBox.Add(item);
}
}
return _myCheckBox;
}
set
{
_myCheckBox = value;
Record.MyEnumCheckBox = 0;
foreach (var item in value)
{
Record.MyEnumCheckBox |= (int)item;
}
}
}
您可以在此处找到有关标志属性的更多信息。它基本上使您能够为单个枚举字段使用多个枚举值,这正是您正在寻找的。
编辑:
我花时间构建了一个自定义模块来演示这种技术。我已经对其进行了测试,并且它以应有的方式工作。所以这里是来源:
迁移.cs
public int Create()
{
SchemaBuilder.CreateTable("MultipleEnumPickerRecord", table => table
.ContentPartRecord()
.Column<int>("SelectedItems"));
ContentDefinitionManager.AlterPartDefinition("MultipleEnumPickerPart", p => p.Attachable());
return 1;
}
楷模:
[Flags]
public enum MyEnum
{
Enum1 = 1, // bit-wise 00001 or 2^0
Enum2 = 2, // bit-wise 00010 or 2^1
Enum3 = 4, // bit-wise 00100 or 2^2
Enum4 = 8, // bit-wise 01000 or 2^3
Enum5 = 16 // bit-wise 10000 or 2^4
}
public class MultipleEnumPickerRecord : ContentPartRecord
{
public virtual int SelectedItems { get; set; }
}
public class MultipleEnumPickerPart : ContentPart<MultipleEnumPickerRecord>
{
private IList<MyEnum> _selectedItems;
public IList<MyEnum> SelectedItems
{
get
{
if (_selectedItems == null)
{
_selectedItems = new List<MyEnum>();
foreach (MyEnum item in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)Record.SelectedItems & item) == item)
_selectedItems.Add(item);
}
}
return _selectedItems;
}
set
{
_selectedItems = value;
Record.SelectedItems = 0;
foreach (var item in value)
{
Record.SelectedItems |= (int)item;
}
}
}
}
处理程序:
public class MultipleEnumPickerHandler : ContentHandler
{
public MultipleEnumPickerHandler(IRepository<MultipleEnumPickerRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
司机:
public class MultipleEnumPickerDriver : ContentPartDriver<MultipleEnumPickerPart>
{
protected override string Prefix { get { return "MultipleEnumPicker"; } }
protected override DriverResult Editor(MultipleEnumPickerPart part, dynamic shapeHelper)
{
return ContentShape("Parts_MultipleEnumPicker_Edit", () => shapeHelper.EditorTemplate(
TemplateName: "Parts/MultipleEnumPicker", Model: part, Prefix: Prefix));
}
protected override DriverResult Editor(MultipleEnumPickerPart part, IUpdateModel updater,
dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
放置:
<Placement>
<Place Parts_MultipleEnumPicker_Edit="Content:5"/>
</Placement>
最后,观点:
@using ModuleNamespace.Models
@model MultipleEnumPickerPart
<fieldset>
<div class="editor-label">@Html.LabelFor(x => x.SelectedItems)</div>
<div class="editor-field">
<select multiple="multiple" id="@Html.FieldIdFor(x => x.SelectedItems)" name="@Html.FieldNameFor(x => x.SelectedItems)">
@foreach (MyEnum item in Enum.GetValues(typeof(MyEnum))) {
var selected = Model.SelectedItems.Contains(item);
<option value="@((int)item)" @if(selected) {<text>selected="selected"</text>}>
@T(item.ToString())
</option>
}
</select>
</div>
</fieldset>
但是,在实施此技术时,您必须牢记两件事:
- 枚举在内部被视为整数,这意味着它们的值占用 32 位。这反过来意味着
MyEnum
不能有超过 32 个枚举项为此定义
- 正如 Bertrand 指出的那样,数据库搜索项目会更难(尽管并非不可能,因为主要数据库允许您使用按位运算符)
这两个约束都可以通过在数据库和模型之间使用不同的映射函数来绕过。
这意味着什么?
在我向您展示的示例中,数据库值(和MultipleEnumPickerRecord
值)是类型int
,而在MultipleEnumPickerPart
我已将该整数“映射”到List<MyEnum>
. 这在数据库中使用的空间更少,并且比使用其他一些映射函数更快。
例如,您可以使用string
数据库的类型,然后对内部MultipleEnumPickerRecord
进行某种映射。最流行的字符串映射函数是List<MyEnum>
MultipleEnumPickerPart
- 逗号分隔的映射 - 例如,如果有人选择
Enum1
and Enum4
,您可以将其映射到字符串"Enum1,Enum4"
- 分号分隔的映射 - 您将前面的示例映射到
"Enum1;Enum4"
要选择的分隔符类型应基于您知道字符串不会使用的字符。要从数据库中的字符串解构列表,您可以使用简单的value.Split(',').ToList();
(如果您使用 ',' 作为分隔符)。
这样一来,您就不会只受到 32 个枚举项的限制,而且由于该值被保存为字符串,因此在数据库中搜索某个值非常简单。缺点是 string 将在数据库中占用更多空间(int 将从字符串中占用一个字符的空间),并且字符串操作函数比上面示例中演示的按位函数要慢一些。