【问题标题】:Rendering an ITemplate in custom markup control in DotVVM在 DotVVM 的自定义标记控件中呈现 ITemplate
【发布时间】:2021-05-04 19:01:25
【问题描述】:

我正在尝试创建一个自定义控件来呈现可以选择日期的日历。我需要能够将ITemplate 传递给每天都会呈现的控件。日子由中继器呈现。

由于目前没有允许绑定到ITemplate 的现有控件(或将ITemplate 与集合以外的任何内容一起使用),我如何轻松地从controlProperty 呈现ITemplate? 我希望有某种只呈现ITemplate 的控件,以便可以在其他地方重用。

部分控制标记:

    <!-- ... -->
    <dot:Repeater ID="DaysRepeater" DataSource="{value: Days}" class="list-group list-group-flush calendar-grid">
        <ItemTemplate>
            <div class="{{value: "calendar-day calendar-day-" + DayOfWeekIndex }}">
                <dot:LinkButton ID="DayButton" class="{{value: "list-group-item list-group-item-action " + (Selected ? "active calendar-day-btn" : "calendar-day-btn") }}"
                                Click="{controlCommand: SelectDate(_this.Date)}">
                    {{value: DayText}}
                    <!-- RENDER TEMPLATE HERE -->
                </dot:LinkButton>
            </div>
        </ItemTemplate>
    </dot:Repeater>

代码隐藏中的ItemTemplate:

        [MarkupOptions(AllowBinding = false, MappingMode = MappingMode.InnerElement, Required = false)]
        [ConstantDataContextChange(typeof(ICollection<CalendarDayModel>)), CollectionElementDataContextChange(1)]
        public ITemplate ItemTemplate
        {
            get { return (ITemplate)GetValue(ItemTemplateProperty)!; }
            set { SetValue(ItemTemplateProperty, value); }
        }

        public static readonly DotvvmProperty ItemTemplateProperty =
            DotvvmProperty.Register<ITemplate, Calendar>(t => t.ItemTemplate);

控件使用示例:

<cc:Calendar DataContext="{value: CalendarViewModel}" MultiSelect="true">
    <ItemTemplate>
        Selected: {{value: Selected}}
    </ItemTemplate>
</cc:Calendar>

【问题讨论】:

    标签: c# .net-core dotvvm


    【解决方案1】:

    不幸的是,我们在 DotVVM 中没有任何可以绑定模板并仅渲染它的控件。但是,您可以执行以下技巧:

    1. 在Repeater的模板中使用PlaceHolder控件:
    <dot:Repeater ID="DaysRepeater" DataSource="{value: Days}" class="list-group list-group-flush calendar-grid">
        <ItemTemplate>
            <div class="{{value: "calendar-day calendar-day-" + DayOfWeekIndex}}">
                <dot:LinkButton ID="DayButton" class="{{value: "list-group-item list-group-item-action " + (Selected ? "active calendar-day-btn" : "calendar-day-btn") }}"
                                Click="{controlCommand: SelectDate(_this.Date)}">
                    {{value: DayText}}
                    <dot:PlaceHolder ID="TemplateHost" />
                </dot:LinkButton>
            </div>
        </ItemTemplate>
    </dot:Repeater>
    
    1. 用你自己的模板替换Repeater模板,它会先渲染原始模板,然后找到占位符,把内部模板放在里面:
    protected override void OnInit(IDotvvmRequestContext context)
    {
        var repeater = (Repeater)FindControlInContainer("DaysRepeater");
        repeater!.ItemTemplate = new TemplateWrapper(ItemTemplate, repeater!.ItemTemplate);
    
        base.OnInit(context);
    }
    
    class TemplateWrapper : ITemplate 
    {
        private readonly ITemplate innerTemplate;
        private readonly ITemplate repeaterTemplate;
    
        public TemplateWrapper(ITemplate innerTemplate, ITemplate repeaterTemplate)
        {
            this.innerTemplate = innerTemplate;
            this.repeaterTemplate = repeaterTemplate;
        }
    
        public void BuildContent(IDotvvmRequestContext context, DotvvmControl container)
        {
            repeaterTemplate.BuildContent(context, container);
    
            var placeholder = container.FindControlInContainer("TemplateHost");
            innerTemplate.BuildContent(context, placeholder!);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 2010-09-20
      • 1970-01-01
      • 2010-10-19
      • 2011-11-24
      • 2012-06-02
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多