在代码中将字段添加到自定义部分的正确方法是什么?

What is the proper way to add a Field to a custom Part in code?

有几个类似的问题可以解决这个问题,例如 this one or 。 None 的人有一个明确的令人满意的答案,或者根本没有答案,或者开始时问的是完全相同的问题。

记录

public class MyPartRecord : ContentPartRecord
{
    public virtual Boolean Property1 { get; set; }
    public virtual string Property2 { get; set; }
}

部分

public class MyPart : ContentPart<MyPartRecord>
{
    public Boolean Property1
    {
        get { return Record.Property1; }
        set { Record.Property1 = value; }
    }

    public string...
}

迁移(由codegen生成)

SchemaBuilder.CreateTable("MyPartRecord", table => table
            .ContentPartRecord()
            .Column("Property1", DbType.Boolean)
            .Column("Property2", DbType.String)
);

ContentDefinitionManager.AlterPartDefinition("MyPart", part => part
    .Attachable()
);

编辑器模板

@model Project.Module.Models.MyPart

<fieldset>
<legend>MyPart</legend>

<!-- Property1 -->
@Html.EditorFor(m => m.Property1)
@Html.LabelFor(m => m.Property1)

...

</fieldset>

这一切都取自关于编写内容部分的官方文档并且工作正常。但是,我希望我的自定义部件也有一个 MediaLibraryPickerField。通过迁移添加一个很容易:

ContentDefinitionManager.AlterPartDefinition("MyPart", part => part
    .WithField("Image", field => field
        .OfType("MediaLibraryPickerField")
        .WithDisplayName("Image")
        .WithSetting("MediaLibraryFieldSettings.Required", "False")
    )
);

但是我在使用这种方法时遇到了几个问题。

1) 我无法在我的模板中呈现该字段,只能使用放置让它显示在模板其余部分上方或下方的某个位置,因此我无法将它与它所属的属性分组.

2) 因为它附加到 MyPart 而不是 MyPart 附加到的类型的 ContentPart,管理员不能通过 GUI 调整它的设置,只能删除它(这是一个错误还是一个功能还没有实施?)。

3) 我不确定如何在代码中访问 MediaLibraryField,因为 ContentItem.MyPart returns 现在是 MyPart 对象,所以 ContentItem.MyPart.Image.FirstMediaUrl 不再有效。

如何解决这些问题?我在这里遗漏了一些明显的东西吗?有没有办法将媒体作为 属性 添加到我的模型而不是使用 Field 并且仍然让 Orchard 保留它?我真的很想避免修改我的 HTML 并将代码从官方实现复制到我的自定义视图。

1) 使用 placement.info 和交替来自定义要呈现字段的位置

2) 您应该可以在 Dashboard -> Content Definition -> YourContentType -> Parts -> MyPart 设置下调整设置。

您也可以将字段附加到类型(注意:它并不是真正附加到类型,而是附加到与类型同名的部分):

Migrations.cs:

ContentDefinitionManager.AlterPartDefinition("MyType", part => part
    .WithField("Image", field => field
        .OfType("MediaLibraryPickerField")
        .WithDisplayName("Image")
        .WithSetting("MediaLibraryFieldSettings.Required", "False")
    )
);

ContentDefinitionManager.AlterTypeDefinition("MyType", type => type
    .WithPart("MyType");

3) 您可以使用动态符号,也可以搜索字段:

// cast to dynamic
var url = ((dynamic)ContentItem).MyPart.Image.FirstMediaUrl

// or search for the field
var field = ContentItem.MyPart.Fields.OfType<MediaLibraryPickerField>().Single(f => f.Name == "Image");
// or ContentItem.MyPart.Fields.Single(f => f.Name == "Image") as MediaLibraryPickerField;
var url = field.FirstMediaUrl;