DotVVM - Code only component DataSource 属性 传入collection时为null
DotVVM - Code only component DataSource property is null when collection is passed in
我有自己的 Accordion 纯代码组件
这是我的视图,其中我有加载 list of article sections
的转发器。每个文章部分有 list of articles
。因此,我想实现每个文章部分都有自己的手风琴,其中将包含 articles
。这就是为什么我把它放在 repeater
<div class="box box-primary">
<dot:Repeater DataSource="{{value: AccordionList}}">
<ItemTemplate>
<coc:Accordion DataSource="{{value: Articles}}"></coc:Accordion>
</ItemTemplate>
</dot:Repeater>
</div>
手风琴代码组件。我的 DataSource
始终为空,即使我清楚地看到 AccordionList
包含永远不会为空的 List of Articles
,但从未传递到我的 DataSource
中。当我将 AccordionList
的类型更改为 ArticleListDTO
并将其直接传递到我的 Accordion
组件时,它运行良好,但这不是我想要的。
public class Accordion : HtmlGenericControl
{
public Accordion() : base("div")
{
}
public static readonly DotvvmProperty DataSourceProperty;
static Accordion()
{
DataSourceProperty = DotvvmProperty.Register<List<ArticleListDTO>, Accordion>(c=>c.DataSource);
}
//DataSource is always null
public List<ArticleListDTO> DataSource
{
get => (List<ArticleListDTO>)GetValue(DataSourceProperty);
set => SetValue(DataSourceProperty, value);
}
protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequestContext context)
{
Attributes.Add("class", "accordion");
base.AddAttributesToRender(writer, context);
}
public void DataBind(IDotvvmRequestContext context)
{
Children.Clear();
foreach (var item in DataSource)
{
DataBindItem(this, item, context);
}
}....etc
视图模型
public List<ArticleSectionListDTO> AccordionList { get; set; } = new List<ArticleSectionListDTO>();
public List<ArticleSectionListDTO> AccordionListUnsorted { get; set; } = new List<ArticleSectionListDTO>();
protected override void OnItemLoading()
{
AccordionListUnsorted = Task.Run(() => articleSectionFacade.GetAllNotModifiedArticleSections()).Result;
AccordionList = Task.Run(() => articleSectionFacade.CreateTree(AccordionListUnsorted, null)).Result.ToList();
}
DTO - 我删除了其余属性以使其清晰
public class ArticleListDTO
{
public string Name { get; set; }
public int? ParentArticleId { get; set; }
public bool HasCategories => AssignedToArticle?.Count > 0;
public List<ArticleListDTO> AssignedToArticle { get; set; }
//Can contain sub articles
public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();
}
public class ArticleSectionListDTO : ListDTO
{
public string Name { get; set; }
public int? ParentArticleSectionId { get; set; }
public bool HasCategories => AssignedToMenuItem?.Count > 0;
public List<ArticleSectionListDTO> AssignedToMenuItem { get; set; }
public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();
}
问题是 Repeater
可能使用客户端呈现模式(这是默认模式)。当它呈现 HTML 时,它呈现如下内容:
<div data-bind="foreach: something">
<!-- template -->
</div>
呈现模板时,它的 DataContext
是 null
(因为模板不能包含项目的数据 - 它是一个模板)。
所以你有两个选择:
- 通过将
RenderSettings.Mode="Server"
添加到 Repeater
打开服务器渲染。
- 更新您的控件,使其在
DataContext
为 null 时不调用 DataBind。
我有自己的 Accordion 纯代码组件
这是我的视图,其中我有加载 list of article sections
的转发器。每个文章部分有 list of articles
。因此,我想实现每个文章部分都有自己的手风琴,其中将包含 articles
。这就是为什么我把它放在 repeater
<div class="box box-primary">
<dot:Repeater DataSource="{{value: AccordionList}}">
<ItemTemplate>
<coc:Accordion DataSource="{{value: Articles}}"></coc:Accordion>
</ItemTemplate>
</dot:Repeater>
</div>
手风琴代码组件。我的 DataSource
始终为空,即使我清楚地看到 AccordionList
包含永远不会为空的 List of Articles
,但从未传递到我的 DataSource
中。当我将 AccordionList
的类型更改为 ArticleListDTO
并将其直接传递到我的 Accordion
组件时,它运行良好,但这不是我想要的。
public class Accordion : HtmlGenericControl
{
public Accordion() : base("div")
{
}
public static readonly DotvvmProperty DataSourceProperty;
static Accordion()
{
DataSourceProperty = DotvvmProperty.Register<List<ArticleListDTO>, Accordion>(c=>c.DataSource);
}
//DataSource is always null
public List<ArticleListDTO> DataSource
{
get => (List<ArticleListDTO>)GetValue(DataSourceProperty);
set => SetValue(DataSourceProperty, value);
}
protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequestContext context)
{
Attributes.Add("class", "accordion");
base.AddAttributesToRender(writer, context);
}
public void DataBind(IDotvvmRequestContext context)
{
Children.Clear();
foreach (var item in DataSource)
{
DataBindItem(this, item, context);
}
}....etc
视图模型
public List<ArticleSectionListDTO> AccordionList { get; set; } = new List<ArticleSectionListDTO>();
public List<ArticleSectionListDTO> AccordionListUnsorted { get; set; } = new List<ArticleSectionListDTO>();
protected override void OnItemLoading()
{
AccordionListUnsorted = Task.Run(() => articleSectionFacade.GetAllNotModifiedArticleSections()).Result;
AccordionList = Task.Run(() => articleSectionFacade.CreateTree(AccordionListUnsorted, null)).Result.ToList();
}
DTO - 我删除了其余属性以使其清晰
public class ArticleListDTO
{
public string Name { get; set; }
public int? ParentArticleId { get; set; }
public bool HasCategories => AssignedToArticle?.Count > 0;
public List<ArticleListDTO> AssignedToArticle { get; set; }
//Can contain sub articles
public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();
}
public class ArticleSectionListDTO : ListDTO
{
public string Name { get; set; }
public int? ParentArticleSectionId { get; set; }
public bool HasCategories => AssignedToMenuItem?.Count > 0;
public List<ArticleSectionListDTO> AssignedToMenuItem { get; set; }
public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();
}
问题是 Repeater
可能使用客户端呈现模式(这是默认模式)。当它呈现 HTML 时,它呈现如下内容:
<div data-bind="foreach: something">
<!-- template -->
</div>
呈现模板时,它的 DataContext
是 null
(因为模板不能包含项目的数据 - 它是一个模板)。
所以你有两个选择:
- 通过将
RenderSettings.Mode="Server"
添加到Repeater
打开服务器渲染。 - 更新您的控件,使其在
DataContext
为 null 时不调用 DataBind。