2012-01-05 170 views
22

我想在網站上使用CDN作爲我的圖像。 問題是,有時我有像ImageButton這樣的服務器控件,我想用一個類來完全提取CDN的路徑。爲此我試着做:服務器標記不能包含<% ... %>構造

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="<%=ResourceManager.GetImageCDN("iagree.png")%>" /> 

和我得到的標題爲錯誤。

只有當我使用<%#它會工作(並且只有當我數據綁定時)。 我該如何輕鬆做到這一點?我如何將CDN代碼放在我的標記代碼上?

謝謝!

回答

23

有四個選項(除了「<%# %>」風格的數據綁定,我不記得ommend):

  1. 在後面的代碼中設置值。這會膨脹ViewState,並且當然需要對控件的每個實例進行代碼更改。
  2. 使用自定義ExpressionBuilder。這不會誇大ViewState,但它確實需要更改所有標記。
  3. 使用控制適配器可以更改應用程序中任何位置的控件行爲;例如,通過在呈現控件之前修改ImageUrl屬性。可以在沒有ViewState影響的情況下完成。
  4. 使用從ImageButton類繼承的類,並結合使用標記映射來在應用程序中使用該類而不是原始位置,並且無需更改標記。可以在沒有ViewState影響的情況下完成。

最好的選擇取決於您的應用程序的要求,但是如果您想在整個站點進行更改,我通常更喜歡使用控制適配器。

下面是一個例子,在情況下,它可以幫助:

using System; 
using System.IO; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Web.UI.WebControls.Adapters; 

namespace Sample 
{ 
    public class ImageButtonControlAdapter : WebControlAdapter 
    { 
     protected override void BeginRender(HtmlTextWriter writer) 
     { 
      ImageButton image = this.Control as ImageButton; 
      if ((image != null) && !String.IsNullOrEmpty(image.ImageUrl)) 
      { 
       // 
       // Decide here which objects you want to change 
       // 
       if (!image.ImageUrl.StartsWith("http") && 
        !image.ImageUrl.StartsWith("data:")) 
       { 
        image.ImageUrl = ResourceManager.GetImageCDN(image.ImageUrl); 
       } 
      } 
      base.BeginRender(writer); 
     } 
    } 
} 

配置成與App_Browers /適配器以下條目您的應用程序。瀏覽器:

<browsers> 
    <browser refID="Default"> 
    <controlAdapters> 
     <adapter controlType="System.Web.UI.WebControls.ImageButton" 
       adapterType="Sample.ImageButtonControlAdapter" /> 
    </controlAdapters> 
    </browser> 
</browsers> 

你的標記是:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="iagree.png" /> 

酷吧?

1

當然,最好的辦法是給ImageButton的一個ID,如:

<asp:ImageButton id="IAgreeImageButton" runat="server" Onclick="Agree" /> 

然後你的網頁加載期間指定IMAGEURL:

void Page_Load(...) 
{ 
    if (!Page.IsPostback) 
    { 
      IAgreeImageButton.ImageUrl = ResourceManager.GetImageCDN("iagree.png"); 
    } 
} 
+1

我在想什麼,以避免CodeBehind – Himberjack 2012-01-05 05:57:21

+2

雖然這種方法將工作,但一個缺點是,它也增加了ViewState(無法禁用,因爲您檢查!IsPostBack)的大小。 – RickNZ 2012-01-05 07:08:10

10

您可以在評估代碼通過創建自己的代碼表達式生成器來創建服這很簡單。

[ExpressionPrefix("Code")] 
public class CodeExpressionBuilder : ExpressionBuilder 
{ 
    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context) 
    { 
     return new CodeSnippetExpression(entry.Expression); 
    } 
} 

而且在你的web.config中的條目:

<compilation debug="true" targetFramework="4.0"> 
    <expressionBuilders> 
     <add expressionPrefix="Code" type="[YourNamespace].CodeExpressionBuilder"/> 
    </expressionBuilders> 
</compilation> 

這可以讓你使用的語法如:

<asp:ImageButton runat="server" ImageUrl='<%$ Code:ResourceManager.GetImageCDN("iagree.png") %>'> 

這裏有一個充分的解釋:http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx

+1

謝謝你的代碼。這正是我正在尋找的。 – Misha 2013-09-12 15:01:06

19

如果有人在將來遇到此線程,可以通過用單引號括住服務器標籤而不是雙引號來獲得所需的結果。

原:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl="<%=ResourceManager.GetImageCDN("iagree.png")%>" /> 

新版本:

<asp:ImageButton runat="server" OnClick="Agree" ImageUrl='<%=ResourceManager.GetImageCDN("iagree.png")%>' /> 

這工作在.NET 4.0中,但我會假設它會在其他版本的工作了。

+1

我本來想多次登錄! – 2015-08-19 08:16:47

+19

這只是輸出包含<%=的實際標籤給我的元素 – 2016-02-18 12:11:59

相關問題