gpt4 book ai didi

asp.net - 如何使用 StylePlaceHolder 和 Style 控件控制 ASP.NET 主题中的样式表

转载 作者:技术小花猫 更新时间:2023-10-29 10:38:55 25 4
gpt4 key购买 nike

更新:这变成了一篇博客文章,更新了链接和代码,在我的博客上:https://egilhansen.com/2008/12/01/how-to-take-control-of-style-sheets-in-asp-net-themes-with-the-styleplaceholder-and-style-control/


问题很简单。使用 ASP.NET 主题时,您对如何将样式表呈现到页面没有太多发言权。

渲染引擎使用

我们都知道样式表的顺序很重要,幸运的是可以通过在样式表前加上 01、02、...、99 来规避 asp.net 的缺点,从而强制按您想要的顺序(参见 Rusty Swayne blog post 有关该技术的更多信息)。

如果您使用我强烈推荐的重置样式表,这一点尤其重要;它使得在浏览器中以一致的形式设置网站样式变得容易得多(看看 Reset Reloaded from Eric Meyer )。

您还错过了指定媒体类型(例如屏幕、打印、投影、盲文、语音)的可能性。如果您更喜欢使用 @import 方法包含样式表,您也会被冷落。

另一个缺少的选项是条件注释,如果您使用“ie-fix.css”样式表,它特别有用。

在我解释 StylePlaceholder 和 Style 控件如何解决上述问题之前,该归功于该功劳,我的解决方案灵感来自 Per Zimmerman’s blog post关于这个问题。

StylePlaceHolder 控件位于母版页或页面的页眉部分。它可以承载一个或多个 Style 控件,默认情况下会删除渲染引擎添加的样式,并添加自己的样式(它只会删除从当前事件主题添加的样式)。

Style 控件既可以在其开始和结束标记之间托管内联样式,也可以通过其 CssUrl 属性引用外部样式表文件。使用其他属性,您可以控制样式表如何呈现到页面。

让我举个例子。考虑一个简单的网站元素,它有一个母版页和一个带有三个样式表的主题——01reset.css、02style.css、99iefix.cs。注意:我使用前面描述的前缀技术命名它们,因为它可以提供更好的设计时体验。另外,自定义控件的标签前缀是“ass:”。

在母版页的页眉部分,添加:

<ass:StylePlaceHolder ID="StylePlaceHolder1" runat="server" SkinID="ThemeStyles" />

在你的主题目录下,添加一个皮肤文件(例如Styles.skin)并添加以下内容:

<ass:StylePlaceHolder1runat="server" SkinId="ThemeStyles">
<ass:Style CssUrl="~/App_Themes/Default/01reset.css" />
<ass:Style CssUrl="~/App_Themes/Default/02style.css" />
<ass:Style CssUrl="~/App_Themes/Default/99iefix.css" ConditionCommentExpression="[if IE]" />
</ass:StylePlaceHolder1>

基本上就是这样。 Style 控件上有更多属性可用于控制渲染,但这是基本设置。有了它,您可以轻松添加另一个主题并替换所有样式,因为您只需要包含一个不同的外观文件。

现在来看实现这一切的代码。我必须承认设计时体验有一些怪癖。可能是因为我对自定义控件的编写不是很熟练(其实这两个是我的第一次尝试),所以很想输入下面的内容。在我正在开发的当前基于 WCAB/WCSF 的元素中,我在 Visual Studios 设计 View 中看到类似这样的错误,我不知道为什么。该站点编译并且一切都在线工作。

Example of design time error in Visual Studio http://www.egil.dk/wp-content/styleplaceholder-error.jpg

以下是 StylePlaceHolder 控件的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;

[assembly: TagPrefix("Assimilated.Extensions.Web.Controls", "ass")]
namespace Assimilated.WebControls.Stylesheet
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[DefaultProperty("SkinID")]
[ToolboxData("<{0}:StylePlaceHolder runat=\"server\" SkinID=\"ThemeStyles\"></{0}:StylePlaceHolder>")]
[ParseChildren(true, "Styles")]
[Themeable(true)]
[PersistChildren(false)]
public class StylePlaceHolder : Control
{
private List<Style> _styles;

[Browsable(true)]
[Category("Behavior")]
[DefaultValue("ThemeStyles")]
public override string SkinID { get; set; }

[Browsable(false)]
public List<Style> Styles
{
get
{
if (_styles == null)
_styles = new List<Style>();
return _styles;
}
}

protected override void CreateChildControls()
{
if (_styles == null)
return;

// add child controls
Styles.ForEach(Controls.Add);
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

// get notified when page has finished its load stage
Page.LoadComplete += Page_LoadComplete;
}

void Page_LoadComplete(object sender, EventArgs e)
{
// only remove if the page is actually using themes
if (!string.IsNullOrEmpty(Page.StyleSheetTheme) || !string.IsNullOrEmpty(Page.Theme))
{
// Make sure only to remove style sheets from the added by
// the runtime form the current theme.
var themePath = string.Format("~/App_Themes/{0}",
!string.IsNullOrEmpty(Page.StyleSheetTheme)
? Page.StyleSheetTheme
: Page.Theme);

// find all existing stylesheets in header
var removeCandidate = Page.Header.Controls.OfType<HtmlLink>()
.Where(link => link.Href.StartsWith(themePath)).ToList();

// remove the automatically added style sheets
removeCandidate.ForEach(Page.Header.Controls.Remove);
}
}

protected override void AddParsedSubObject(object obj)
{
// only add Style controls
if (obj is Style)
base.AddParsedSubObject(obj);
}

}
}

以及样式控件的代码:

using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;

[assembly: TagPrefix("Assimilated.Extensions.Web.Controls", "ass")]
namespace Assimilated.WebControls.Stylesheet
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[DefaultProperty("CssUrl")]
[ParseChildren(true, "InlineStyle")]
[PersistChildren(false)]
[ToolboxData("<{0}:Style runat=\"server\"></{0}:Style>")]
[Themeable(true)]
public class Style : Control
{
public Style()
{
// set default value... for some reason the DefaultValue attribute do
// not set this as I would have expected.
TargetMedia = "All";
}

#region Properties

[Browsable(true)]
[Category("Style sheet")]
[DefaultValue("")]
[Description("The url to the style sheet.")]
[UrlProperty("*.css")]
public string CssUrl
{
get; set;
}

[Browsable(true)]
[Category("Style sheet")]
[DefaultValue("All")]
[Description("The target media(s) of the style sheet. See http://www.w3.org/TR/REC-CSS2/media.html for more information.")]
public string TargetMedia
{
get; set;
}

[Browsable(true)]
[Category("Style sheet")]
[DefaultValue(EmbedType.Link)]
[Description("Specify how to embed the style sheet on the page.")]
public EmbedType Type
{
get; set;
}

[Browsable(false)]
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public string InlineStyle
{
get; set;
}

[Browsable(true)]
[Category("Conditional comment")]
[DefaultValue("")]
[Description("Specifies a conditional comment expression to wrap the style sheet in. See http://msdn.microsoft.com/en-us/library/ms537512.aspx")]
public string ConditionalCommentExpression
{
get; set;
}

[Browsable(true)]
[Category("Conditional comment")]
[DefaultValue(CommentType.DownlevelHidden)]
[Description("Whether to reveal the conditional comment expression to downlevel browsers. Default is to hide. See http://msdn.microsoft.com/en-us/library/ms537512.aspx")]
public CommentType ConditionalCommentType
{
get; set;
}

[Browsable(true)]
[Category("Behavior")]
public override string SkinID { get; set; }

#endregion

protected override void Render(HtmlTextWriter writer)
{
// add empty line to make output pretty
writer.WriteLine();

// prints out begin condition comment tag
if (!string.IsNullOrEmpty(ConditionalCommentExpression))
writer.WriteLine(ConditionalCommentType == CommentType.DownlevelRevealed ? "<!{0}>" : "<!--{0}>",
ConditionalCommentExpression);

if (!string.IsNullOrEmpty(CssUrl))
{
// add shared attribute
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");

// render either import or link tag
if (Type == EmbedType.Link)
{
// <link href=\"{0}\" type=\"text/css\" rel=\"stylesheet\" media=\"{1}\" />
writer.AddAttribute(HtmlTextWriterAttribute.Href, ResolveUrl(CssUrl));
writer.AddAttribute(HtmlTextWriterAttribute.Rel, "stylesheet");
writer.AddAttribute("media", TargetMedia);
writer.RenderBeginTag(HtmlTextWriterTag.Link);
writer.RenderEndTag();
}
else
{
// <style type="text/css">@import "modern.css" screen;</style>
writer.RenderBeginTag(HtmlTextWriterTag.Style);
writer.Write("@import \"{0}\" {1};", ResolveUrl(CssUrl), TargetMedia);
writer.RenderEndTag();
}
}

if(!string.IsNullOrEmpty(InlineStyle))
{
// <style type="text/css">... inline style ... </style>
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");
writer.RenderBeginTag(HtmlTextWriterTag.Style);
writer.Write(InlineStyle);
writer.RenderEndTag();
}

// prints out end condition comment tag
if (!string.IsNullOrEmpty(ConditionalCommentExpression))
{
// add empty line to make output pretty
writer.WriteLine();
writer.WriteLine(ConditionalCommentType == CommentType.DownlevelRevealed ? "<![endif]>" : "<![endif]-->");
}
}
}

public enum EmbedType
{
Link = 0,
Import = 1,
}

public enum CommentType
{
DownlevelHidden = 0,
DownlevelRevealed = 1
}
}

那么大家怎么看呢?这是解决asp.net主题问题的好方法吗?那代码呢?我真的很想得到一些意见,尤其是在设计时体验方面。

我上传了一个 zipped version of the Visual Studio solution包含该元素,以防有人感兴趣。

最好的问候,埃吉尔。

最佳答案

找到了我自己问题的答案。

我在设计模式下出现渲染错误的原因是 Visual Studio SP1 中的明显错误,which Microsoft has yet to fix .

因此,只要您仅将自定义控件包含在预编译的程序集中,而不是通过同一解决方案中的另一个元素,上述代码就可以在设计模式下按预期工作。

有关如何以及为什么的更详细说明,请参见上面的链接。

关于asp.net - 如何使用 StylePlaceHolder 和 Style 控件控制 ASP.NET 主题中的样式表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/328763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com