要查看主题和外观的工作方式,请将以下指令添加到DataSource2.aspx中,如图2 所示:
<html>
<body>
<form runat="server">
<asp:SqlDataSource ID="Countries" RunAt="server"
ConnectionString="server=localhost;database=northwind;
Integrated Security=SSPI"
SelectCommand="select distinct country from customers order by country"
EnableCaching="true" CacheDuration="60"
/>
<asp:SqlDataSource ID="Customers" RunAt="server"
ConnectionString="server=localhost;database=northwind;
Integrated Security=SSPI"
SelectCommand="select * from customers where country=@country"
>
<SelectParameters>
<asp:ControlParameter Name="Country"
ControlID="MyDropDownList"
PropertyName="SelectedValue"
/>
</SelectParameters>
</asp:SqlDataSource>
<asp:DropDownList ID="MyDropDownList" DataSourceID="Countries"
DataTextField="country" AutoPostBack="true" RunAt="server"
/>
<asp:DataGrid DataSourceID="Customers" RunAt="server" />
</form>
</body>
</html>
图2 DataSource2.aspx
现在刷新该页面。结果如图3中所示。
图3 主题和外观的工作方式
接下来,赋予该页面完全不同的外观,方法是:添加一个元素,并且更改@ Page指令以指示要使用的页面主题:
@ Page指令的新Theme属性以声明方式将主题应用到页面中。还可以使用Page类的Theme属性以编程方式应用主题。主题是外观的集合,而外观是应用于一个控件类型的一组可视属性。BasicBlue和SmokeAndGlass是ASP.NET 2.0附带的几个预定义(或全局)主题中的两个。您可以在Microsoft.NET/Framework/.../ ASP.NETClientFiles/Themes下的子目录中找到它们。
您可以定义自己的主题和外观,并且自定义地将它们部署到应用程序Themes目录的子目录中。每个子目录构成一个主题,并且主题名称与子目录名称相同。一个主题子目录包含一个或多个.skin文件以及该主题使用的任何其他资源(例如,图像文件和样式表)。实际的外观定义包含在.skin文件中,并且非常类似于用来在ASPX文件中声明控件实例的标记。
为说明这一点,请在包含DataSource2.aspx的文件夹中创建一个名为Themes的子目录。在该Themes目录中,创建一个名为ShockingPink的子目录。将以下内容复制到ShockingPink目录中的新建的.skin文件中:
<asp:DropDownList runat="server" BackColor="hotpink" ForeColor="white" />
<asp:DataGrid runat="server" BackColor="#CCCCCC" BorderWidth="2pt"
BorderStyle="Solid" BorderColor="#CCCCCC" GridLines="Vertical"
HorizontalAlign="Left"
>
<HeaderStyle ForeColor="white" BackColor="hotpink" />
<ItemStyle ForeColor="black" BackColor="white" />
<AlternatingItemStyle BackColor="pink" ForeColor="black" />
</asp:DataGrid>
接下来,将DataSource2.aspx中的@ Page指令更改为:
<%@ Page Theme="ShockingPink" %>
上述操作的结果无疑是曾经创建过的最为华丽的Web页之一。
ShockingPink.skin定义了DropDownList和DataGrid控件的默认外观。外观文件不必与它们所属的主题具有相同的名称(尽管它们通常如此)。一个主题可以包含多个.skin文件,而单个.skin文件可以为任意数量的控件类型定义属性。此外,ASP.NET还可以区分默认外观和非默认外观。根据定义,缺少SkinID属性的外观是默认外观。非默认外观包含可以通过控件标记中的SkinID属性引用的SkinID。
新增控件
ASP.NET 2.0将引入大约50种新的控件类型,以便帮助您生成丰富的用户界面,同时使您无须应付HTML、客户端脚本和浏览器文档对象模型(DOM)的各种变幻莫测的行为。“新增控件”提要栏列出了直至本文撰写时规划的新控件(Web部件控件除外)。
DynamicImage控件简化了在Web页中显示动态生成的图像的任务。在过去,开发人员经常编写自定义HTTP处理程序来处理动态图像生成,甚至更糟糕的是,处理ASPX文件中生成的图像。DynamicImage使得这两种技术都过时了。图4 中的代码使用DynamicImage控件来绘制饼图。关键语句是那个将图像位分配给控件的ImageBytes数组的语句。
DynamicImage控件利用了新增的ASP.NET 2.0图像生成服务。另一种访问图像生成服务的方法是,在ASP.NET 2.0的全新ASIX文件中动态生成图像。本文随附的示例文件(可从MSDN Magazine Web站点上获得)包含一个名为DynamicImage.asix的文件,它展示了ASIX文件的要素。要运行该文件,请将DynamicImage.asix复制到Web服务器的某个虚拟目录中,然后在浏览器中激活该文件。
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.IO" %>
<html>
<body>
<asp:DynamicImage ID="PieChart" DynamicImageType="ImageBytes"
RunAt="server"
/>
</body>
</html>
<script language="C#" runat="server">
void Page_Load (Object sender, EventArgs e)
{
// Create a bitmap and draw a pie chart
Bitmap bitmap = new Bitmap (240, 180, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage (bitmap);
DrawPieChart (g, Color.White, new decimal[]
{ 100.0m, 200.0m, 300.0m, 400.0m }, 240, 180);
g.Dispose();
// Attach the image to the DynamicImage control
MemoryStream stream = new MemoryStream ();
bitmap.Save (stream, ImageFormat.Gif);
bitmap.Dispose();
PieChart.ImageBytes = stream.ToArray ();
}
void DrawPieChart (Graphics g, Color bkgnd, decimal[] vals, int width, int height)
{
// Erase the background
SolidBrush br = new SolidBrush (bkgnd);
g.FillRectangle (br, 0, 0, width, height);
br.Dispose ();
// Create an array of brushes
SolidBrush[] brushes = new SolidBrush[6];
brushes[0] = new SolidBrush (Color.Red);
brushes[1] = new SolidBrush (Color.Yellow);
brushes[2] = new SolidBrush (Color.Blue);
brushes[3] = new SolidBrush (Color.Cyan);
brushes[4] = new SolidBrush (Color.Magenta);
brushes[5] = new SolidBrush (Color.Green);
// Sum the inputs
decimal total = 0.0m;
foreach (decimal val in vals)
total += val;
// Draw the chart
float start = 0.0f;
float end = 0.0f;
decimal current = 0.0m;
for (int i=0; i<vals.Length; i++)
{
current += vals[i];
start = end;
end = (float) (current / total) * 360.0f;
g.FillPie (brushes[i % 6], 0.0f, 0.0f, width, height,
start, end - start);
}
// Clean up and return
foreach (SolidBrush brush in brushes)
brush.Dispose ();
}
</script>
图4 DynamicImage.aspx
ASP.NET 2.0中首次亮相的另一个有趣且非常有用的控件是MultiView控件。与View控件搭配使用时,MultiView可用来创建包含多个逻辑视图的页面。一次只能显示一个视图(其索引被分配给MultiView的ActiveViewIndex属性的那个视图),但您可以通过更改活动视图索引来切换视图。对于使用选项卡或其他控件来让用户在逻辑页之间进行导航的页面而言,MultiViews是非常理想的。
图5 中的页面使用一个MultiView来显示Pubs数据库Titles表的两个不同视图:其中一个用GridView呈现,另一个用DetailsView呈现。视图切换是通过从下拉列表中进行选择来完成的。请注意,标记中的AllowPaging属性使用户可以浏览DetailsView中的记录。
<%@ Page Theme="BasicBlue" %>
<html>
<body>
<form runat="server">
<asp:SqlDataSource ID="Titles" RunAt="server"
ConnectionString="server=localhost;database=pubs;
Integrated Security=SSPI"
SelectCommand="select title_id, title, price from titles"
/>
<asp:DropDownList ID="ViewType" AutoPostBack="true"
OnSelectedIndexChanged="OnSwitchView" RunAt="server"
>
<asp:ListItem Text="GridView" Selected="true" RunAt="server" />
<asp:ListItem Text="DetailsView" RunAt="server" />
</asp:DropDownList>
<asp:MultiView ID="Main" ActiveViewIndex="0" RunAt="server">
<asp:View RunAt="server">
<asp:GridView DataSourceID="Titles" RunAt="server" />
</asp:View>
<asp:View RunAt="server">
<asp:DetailsView DataSourceID="Titles" AllowPaging="true"
RunAt="server"
/>
</asp:View>
</asp:MultiView>
</form>
</body>
</html>
<script language="C#" runat="server">
void Page_Load (Object sender, EventArgs e)
{
if (IsPostBack)
DataBind ();
}
void OnSwitchView (Object sender, EventArgs e)
{
Main.ActiveViewIndex = ViewType.SelectedIndex;
}
</script>
图5 MultiView.aspx