Cập nhật: này biến thành một bài đăng blog, với các liên kết được cập nhật và mã, qua tại blog của tôi: https://egilhansen.com/2008/12/01/how-to-take-control-of-style-sheets-in-asp-net-themes-with-the-styleplaceholder-and-style-control/Làm thế nào để kiểm soát style sheets trong ASP.NET Chủ đề với StylePlaceHolder và Phong cách kiểm soát
Vấn đề khá đơn giản. Khi sử dụng ASP.NET Chủ đề bạn không có nhiều nói trong cách phong cách của bạn tờ được trả lại cho trang.
Công cụ hiển thị thêm tất cả các mẫu kiểu bạn có trong thư mục chủ đề của bạn theo thứ tự chữ cái, sử dụng ký hiệu < link href = ”...”.
Chúng ta đều biết thứ tự của các tờ mẫu là quan trọng, may mắn asp.nets thiếu sót có thể được circumvented bởi tiền tố phong cách tờ với 01, 02, ..., 99, và do đó buộc thứ tự bạn muốn (xem Rusty Swayne blog post về kỹ thuật này để biết thêm thông tin).
Điều này đặc biệt quan trọng nếu bạn sử dụng bảng định kiểu đặt lại, mà tôi đặc biệt khuyên dùng; nó giúp việc tạo kiểu trang web trong một biểu mẫu nhất quán dễ dàng hơn trên các trình duyệt (xem Reset Reloaded from Eric Meyer).
Bạn cũng bỏ lỡ khả năng chỉ định loại phương tiện (ví dụ: màn hình, in, chiếu, chữ nổi, lời nói). Và nếu bạn muốn bao gồm các tờ kiểu bằng cách sử dụng phương pháp @import, bạn cũng bị loại bỏ trong điều kiện lạnh.
Một tùy chọn còn thiếu khác là Nhận xét có điều kiện, đặc biệt hữu ích nếu bạn sử dụng biểu định kiểu "ie-fix.css".
Trước khi tôi giải thích cách kiểm soát StylePlaceholder và Style giải quyết các vấn đề trên, tín dụng khi tín dụng đến hạn, giải pháp của tôi được lấy cảm hứng từ Per Zimmerman’s blog post về chủ đề.
Điều khiển StylePlaceHolder được đặt trong phần tiêu đề của trang chính hoặc trang chính của bạn. Nó có thể lưu trữ một hoặc nhiều điều khiển kiểu và sẽ xóa kiểu được công cụ hiển thị thêm vào theo mặc định và thêm kiểu của riêng nó (nó sẽ chỉ xóa kiểu được thêm từ chủ đề hiện hoạt hiện tại).
Kiểm soát kiểu có thể lưu trữ kiểu nội tuyến ở giữa thẻ mở và đóng và tham chiếu đến tệp trang tính ngoài thông qua thuộc tính CssUrl của nó. Với các thuộc tính khác, bạn kiểm soát cách biểu định kiểu mà nó hiển thị cho trang.
Hãy để tôi hiển thị ví dụ. Hãy xem xét một dự án trang web đơn giản với một trang cái và một chủ đề với ba tờ định kiểu - 01reset.css, 02style.css, 99iefix.cs. Lưu ý: Tôi đã đặt tên cho chúng bằng cách sử dụng kỹ thuật tiền tố được mô tả trước đó, vì nó làm cho trải nghiệm thiết kế tốt hơn. Ngoài ra, tiền tố thẻ của các điều khiển tùy chỉnh là “ass:”.
Trong phần tiêu đề trang thạc sĩ, thêm:
<ass:StylePlaceHolder ID="StylePlaceHolder1" runat="server" SkinID="ThemeStyles" />
Trong thư mục chủ đề của bạn, thêm một tập tin da (ví dụ Styles.skin) và thêm các nội dung sau đây:
<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>
Đó là về cơ bản nó. Có nhiều thuộc tính hơn trên điều khiển Kiểu có thể được sử dụng để kiểm soát hiển thị, nhưng đây là thiết lập cơ bản. Với điều đó tại chỗ, bạn có thể dễ dàng thêm một chủ đề khác và thay thế tất cả các kiểu, vì bạn chỉ cần bao gồm một tệp da khác.
Bây giờ đến mã khiến mọi thứ xảy ra. Tôi phải thừa nhận rằng kinh nghiệm thiết kế thời gian có một số quirks.Có lẽ là do tôi không thành thạo trong việc viết các điều khiển tùy chỉnh (trên thực tế, hai điều này là những nỗ lực đầu tiên của tôi), vì vậy tôi rất thích đầu vào như sau. Trong một dự án WCAB/WCSF hiện tại tôi đang phát triển, tôi thấy lỗi như thế này trong quan điểm thiết kế của Visual Studios, và tôi không biết tại sao. Trang web biên dịch và mọi thứ hoạt động trực tuyến.
Sau đây là mã cho sự kiểm soát 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);
}
}
}
Và mã cho điều khiển Kiểu:
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
}
}
Vậy điều gì làm bạn nghĩ? Đây có phải là một giải pháp tốt cho vấn đề chủ đề asp.net? Và những gì về mã? Tôi thực sự muốn một số đầu vào vào nó, đặc biệt là liên quan đến kinh nghiệm thời gian thiết kế.
Tôi đã tải lên zipped version of the Visual Studio solution có chứa dự án, trong trường hợp ai đó quan tâm.
Trân trọng, Egil.
Cảm ơn các từ loại Simon. Điều này thực sự là điều khiển tùy chỉnh đầu tiên của tôi, nó đã được tái cấu trúc một vài lần ngay bây giờ, vì vậy điều khiển tùy chỉnh đầu tiên, không phải lần đầu tiên :) –
@egil điều buồn cười là tôi chuyển sang MVC ngày hôm sau - một phần vì tôi đã mệt mỏi phải đi tìm các giải pháp thông minh như của bạn cho những vấn đề đơn giản. may mắn thay tôi đang phát triển một trang web mới vì vậy tôi đã được phép sang trọng để chơi với MVC và tôi thực sự thích nó –