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

时间:2016-04-21 10:30:42

标签: orchardcms orchardcms-1.9

有几个类似的问题可以处理这个问题,例如this onethis one offering a pretty hacky solution。那些人中没有一个人有一个明确令人满意的答案,或者一个答案,或者从一开始就要求完全相同的事情。

记录

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>

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

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

但是我使用这种方法遇到了一些问题。

1)我无法在模板中渲染字段,只使用展示位置将其显示在模板其余部分的上方或下方,因此我无法将其与其所属的属性进行分组。 / p>

2)由于它附加到MyPart而不是MyPart附加的Type的ContentPart,因此管理员无法通过GUI调整其设置,只能删除它(这是一个bug还是一个尚未成功的功能执行吗?)。

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

如何解决这些问题?我错过了一些明显的东西吗?有没有办法将Media作为属性添加到我的模型而不是使用Field并且仍然让Orchard坚持下去?我真的想避免修改我的HTML并将代码从官方实现复制到我的自定义视图。

1 个答案:

答案 0 :(得分:3)

1)使用placement.info和替代来自定义要渲染字段的位置

2)您应该能够调整仪表板中的设置 - &gt;内容定义 - &gt; YourContentType - &gt;零件 - &gt;在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;