为 ASP.Net Control 的属性设置动态值
我试图将动态变量传递到控件中:
<% foreach(var product in CartModel.Products) { %>
<kc:Warning runat="server" id="Warning" ProductId="<%= product.ProductId %>" />
%>
但是当我访问控件中的 ProductId(在 /ProductAvailabilityWarning.ascx.cs 中)时,它会按字面意思传递 "<%= Product.ProductId %>; "
,而不是 product.ProductId
的值。
我不想将所有代码重写为 Repeater,因为 foreach 块内有大量我必须修改的动态代码。
编辑:由于这段代码看起来很混乱,因为它是遗留代码的弗兰肯斯坦怪物,这里有一个更完整的代码片段,以及为什么我试图避免将整个代码重写为中继器
<% foreach(var product in CartModel.Products) { %>
<kc:Warning runat="server" id="Warning" ProductId="<%= product.ProductId %>" />
<div class="cart-product js-cart-product">
<div class="cart-product__product-details">
<div class="cart-product__name"><%= product.ProductName %></div>
<div class="cart-product__details">
<div class="cart-product__detail-label"><%= product.MaturityLabel %></div>
<div class="cart-product__detail-description"><%= product.RelativeMaturity %> <%= Dictionary.GetValue("eBusiness", "days" ) %></div>
<ul class="cart-product__detail-icons">
<% foreach(var maturityIcon in product.MaturityIcons) { %>
<li>
<img
src="<%= maturityIcon.Src %>"
alt="" />
<span class="badge-label"><%= maturityIcon.Alt %></span>
</li>
<% } %>
</ul>
</div>
<div class="cart-product__treatments-label">
<%= Dictionary.GetValue("eBusiness", "seed treatments selected" ) %>
</div>
<ul class="cart-product__treament-grid">
<% foreach(var seedTreatmentImage in product.SeedTreatmentImages) { %>
<li class="cart-product__selected-treatment">
<img
src="<%= seedTreatmentImage.Src %>"
alt="<%= seedTreatmentImage.Alt %>" />
</li>
<% } %>
</ul>
</div>
<div class="cart-product__order-totals">
<% if (product != null && product.ProductBagImage != null) { %>
<div class="cart-product__logo">
<img width="325" height="500"
src="<%= product.ProductBagImage.Src %>"
alt="<%= product.ProductBagImage.Alt %>" />
</div>
<% } %>
<div class="cart-product__quantity">
<span class="cart-product__value"><%= product.Quantity %></span>
<% if (product.Size == eBusiness.Sizes.Bag) { %>
<span class="cart-product__label"><%= Dictionary.GetValue("eBusiness", "size_bags" ) %></span>
<% } else if (product.Size == eBusiness.Sizes.Tote) { %>
<span class="cart-product__label"><%= Dictionary.GetValue("eBusiness", "size_totes" ) %></span>
<% } else if (product.Size == eBusiness.Sizes.SeedPak) { %>
<span class="cart-product__label"><%= Dictionary.GetValue("eBusiness", "size_seedpaks" ) %></span>
<% } %>
</div>
<div class="cart-product__acres">
<span class="cart-product__value"><%= product.Acres %></span>
<span class="cart-product__label"><%= Dictionary.GetValue("eBusiness", "acres") %></span>
</div>
<div class="cart-product__divider"></div>
<div class="cart-product__total">
<sup class="cart-product__currency">$</sup>
<span class="cart-product__value"><%= product.Msrp.ToString("0,0.00") %></span>
<span class="cart-product__label"><%= Dictionary.GetValue("eBusiness", "MSRP") %></span>
</div>
</div>
<% if(ShowRemoveButton){ %>
<div class="cart-product__remove">
<button
class="cart-product__cta-button js-cart-product__remove"
type="button"
data-bundle-id="<%= product.BundleId %>">
<img src="/build/img/svg-sprite/icon-garbage.svg" alt="" />
<span><%= Dictionary.GetValue("eBusiness", "remove") %></span>
</button>
</div>
<% } %>
<% if(ShowEditButton){ %>
<div class="cart-product__edit">
<a href='<%= ProductCustomizationBaseUrl + product.ProductId + "&c=" + product.BundleId %>' class="cart-product__cta-button">
<img src="/build/img/icon-edit.svg" alt="" />
<span><%= Dictionary.GetValue("eBusiness", "edit") %></span>
</a>
</div>
<% } %>
</div>
<% } %>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
控件语法,控件不会像那样工作。Init
(IIRC) 中实例化,然后在__VIEWDATA
的反序列化事件中设置其属性,并在数据绑定事件中再次设置(但仅适用于<%# %>
样式语法)。<%= %>
语法表示调用HtmlTextWriter.Write()
,它只是将内部字符串值写入输出流,而且它只是在页面的渲染函数期间调用:因此<%= %> 语法不能用于设置控件的属性(仅
<%# %>
可以用于此目的,但前提是您使用 WebForms 的(非常复杂的)数据绑定系统。UserControl
(又名.ascx
)并使用。它渲染 HTML,而不会影响 WebForm 的控件生命周期,并且古老而可怕的数据绑定系统好消息是:你可以!
像这样:
Page.LoadControl(String virtualPath)
获取代表用户控件的Control
对象实例。virtualPath
参数将是一个const String
,如~/MyControls/Warning.ascx
或类似的。UserControl
子类(在.ascx
的代码隐藏文件中定义的类型。RenderControl
,从.aspx
的渲染函数传递(隐藏的)__w
对象,如下所示:
MyPage.aspx:
如果添加自定义,您可以稍微简化事情
Render
函数到您的UserControl
的代码隐藏类,如下所示:此外,如果您喜欢冒险(并且在 .NET Framework 上运行),您还可以使用 ASP.NET Core 风格的构造函数依赖注入到您的
UserControl
中4.7.2 或更高版本)然后您的
.aspx
逻辑简化为:更简单!
如果您想知道
__w
来自哪里:它就是HTML 被写入的 HtmlTextWriter
它作为参数传递到从.aspx
文件生成的渲染函数中。您可以通过将
aspnet_compiler.exe
生成的.dll
文件加载到 ILSpy 中并在中找到生成的
子类,例如:__Render_controlN
方法来亲自查看它Page因此每次出现
<%= x %>
和<%: y %>
转换为__w.Write(x);
和__w.Write(HttpUtility.HtmlEncode(y)); 分别。
...这也解释了为什么是一个具有自己的逻辑和渲染函数的对象,而不仅仅是通过
:因为HtmlTextWriter。
<kc:Warning/>
control syntax, controls don't work like that.Init
(IIRC), then have their properties set during__VIEWDATA
's deserialization events and again in the data-binding events (but only for<%# %>
-style syntax).<%= %>
syntax denotes a call toHtmlTextWriter.Write()
which simply writes the inner string value to the output stream, and it's only invoked during the page's render-function: so the<%= %>
syntax cannot be used to set properties of controls (only<%# %>
can be used for that, but only if you're using WebForms' (horribly complicated) data-binding system.UserControl
(aka.ascx
) and just use it render HTML without faffing around with WebForm's control lifecycle andold-and-horrible data-binding system the good news is: you can!
Like so:
Page.LoadControl(String virtualPath)
to get aControl
object instance representing your user-control.virtualPath
argument will be aconst String
like~/MyControls/Warning.ascx
or similar.UserControl
subclass (the type defined in your.ascx
's code-behind file.RenderControl
, passing the (hidden)__w
object from your.aspx
's render function.Like so:
MyPage.aspx:
You can simplify things somewhat if you add a custom
Render
function to yourUserControl
's code-behind class, like so:Also, you can also use ASP.NET Core-style constructor-dependency injection into your
UserControl
's if you're feeling adventurous (and are running on .NET Framework 4.7.2 or later).Then your
.aspx
logic simplifies down to just this:Much simpler!
If you're wondering where
__w
comes from: it's theHtmlTextWriter
where your HTML is being written to. It's passed as a parameter into the render function generated from your.aspx
file.You can see it yourself by loading the
.dll
file generated byaspnet_compiler.exe
into ILSpy and locating the generated__Render_controlN
method in yourPage
subclass, for example:So every occurrence of
<%= x %>
and<%: y %>
is converted to__w.Write(x);
and__w.Write(HttpUtility.HtmlEncode(y));
respectively....which also explains why
<asp:SomeControl runat="server" PropertyName="<%= x %>" />
isn't allowed: because<asp:SomeControl
is an object with its own logic and render function, and not just plaintext that's passed throughHtmlTextWriter
.