65.9K
CodeProject 正在变化。 阅读更多。
Home

通过ASP.NET理解WPF

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (43投票s)

2008 年 5 月 22 日

CPOL

6分钟阅读

viewsIcon

165657

downloadIcon

2501

展示了如何通过ASP.NET轻松理解某些WPF概念。

引言

和许多人一样,我很难掌握WPF,因为它在编写桌面应用程序时似乎非常“陌生”。它看起来非常不同,我无法应用我已有的知识——然后有一天,我突然明白了。我一直从错误的角度来处理这个问题,完全错误。通过应用ASP.NET的思维方式,我可以将我知道的东西与WPF联系起来。显然,WPF提供的远不止这些,但它给了我一个良好的开端。

我们不会深入探讨WPF。我将展示用ASP.NET和WPF编写的同一个应用程序,并看看代码的不同部分是如何关联的。我们还将看看WPF的一些根本区别,尽管表面上看它们是相同的。

本文并非旨在研究无状态和有状态应用程序之间的差异。我们不会担心往返和状态维护等问题。

概述

在我们继续之前,让我们来看看我们要创建的应用程序。这是一个从XML文件读取数据并在列表中显示的简单应用程序。里面没有什么复杂的东西,我们将完成所有“巧妙”的工作。我们要绑定到数据如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<People>
    <Person Name="Josh" Handle="RockStar" IQ="10000" />
    <Person Name="Sacha" Handle="The Bloginator" IQ="10000" />
    <Person Name="Karl" Handle="The MoleMan" IQ="10000" />
    <Person Name="Pete" Handle="Pretender to the throne" IQ="10" />
</People>

ASP.NET应用程序看起来是这样的:

Picture1.jpg

WPF应用程序看起来是这样的:

picture2.jpg

ASP.NET应用程序

这里显示的是ASP.NET应用程序的代码:

<%@ Page Language="C#" AutoEventWireup="true" 
        CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head runat="server">
    <title>Sample App</title>
    <style type="text/css" media="all">
      td 
      { 
        font-family : Tahoma; 
        font-size : 10px; 
      }
      .iqStyle
      {
        font-family : Verdana;
        font-size : 14px;
        font-style : italic;
      }
    </style>
  </head>
  <body>
    <form id="form1" runat="server">
      <div>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataSourceID="XmlDataSource1" ShowHeader="False">
          <Columns>
            <asp:BoundField DataField="Name" />
            <asp:BoundField DataField="Handle" />
            <asp:BoundField DataField="IQ" ItemStyle-CssClass="iqStyle" />
          </Columns>
        </asp:GridView>
      </div>
      <asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/Sample.xml" 
        XPath="/People/Person"></asp:XmlDataSource>
    </form>
  </body>
</html>

正如你所见,它并不复杂。基本上,我们创建了一个XmlDataSource并将其绑定到一个GridView。我们手动添加了几种样式来控制格式,但这里没有复杂的代码。绑定在这里都已为我们处理好了。

WPF应用程序

现在,让我们来看看WPF版本的代码:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2006" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
  x:Class="WpfSampleApp.Window1"
  x:Name="Window"
  Title="Sample App"
  Width="380" Height="240">
  <Window.Resources>
    <XmlDataProvider x:Key="PeopleSource" d:IsDataSource="True" Source="Sample.xml"/>
    <Style TargetType="ListBox">
      <Setter Property="Control.FontFamily" Value="Tahoma" />
      <Setter Property="Control.FontSize" Value="10" />
    </Style>
    <Style x:Key="FontStyle">
      <Setter Property="Control.FontFamily" Value="Verdana" />
      <Setter Property="Control.FontStyle" Value="Italic" />
      <Setter Property="Control.FontSize" Value="12"/>
    </Style>
    <DataTemplate x:Key="PersonTemplate">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <TextBlock Width="40" Grid.Column="0" 
         Text="{Binding Mode=OneWay, XPath = @Name}" />
      <TextBlock Width="130" Grid.Column="1" 
         Text="{Binding Mode=OneWay, XPath=@Handle}" />
      <TextBlock Width="Auto" Grid.Column="2" 
        Text="{Binding Mode=OneWay, XPath = @IQ}" 
        Style="{StaticResource FontStyle}" />
    </Grid>
    </DataTemplate>
  </Window.Resources>
  <Grid x:Name="LayoutRoot">
    <ListBox Padding="3" HorizontalAlignment="Left" Width="Auto" 
      ItemTemplate="{DynamicResource PersonTemplate}" 
      ItemsSource="{Binding Mode=Default, Source={StaticResource PeopleSource}, 
      XPath=/People/Person}" VerticalAlignment="Top" Height="Auto"/>
  </Grid>
</Window>

我使用Expression Blend来组合这个(提示——如果你认真对待WPF,那么你真的需要获取Blend;它会让你的生活变得轻松很多)。它使用XmlDataSource绑定到一个ListBox,我们将对其进行格式化以显示XML文件中的数据。再次注意,我没有写一行C#代码——所有这些都是在XAML中完成的。

样式

如前所述,我们在ASP.NET应用程序中创建了几种样式。同样,我们在WPF应用程序中创建了几种样式,它们做了大致相同的事情。在本节中,我们将看看我们创建的两种类型的样式。

类型选择器

在CSS中,类型选择器允许你将样式匹配到文档树中该类型的所有实例。因此,我们将把每个TD元素的字体更改为10px Tahoma

WPF允许你通过创建应用于特定TargetType的样式来实现相同的功能。在我们的示例中,我们将窗口中每个ListBox的字体大小更改为10号Tahoma。

细心的读者会注意到,我没有说ListBox中的字体大小是10像素。这是WPF中需要适应的第一个变化之一,即WPF是分辨率无关的。这意味着我们不再以像素为单位来思考问题——所以,在96DPI显示器上的一英寸按钮,在140DPI显示器上仍然是一英寸按钮。

命名样式

在ASP.NET应用程序中,我们创建了一个命名样式,将字体更改为12px斜体Verdana。同样,WPF也允许我们设置一个命名样式,将字体更改为12号斜体Verdana。要在ASP.NET中应用样式,我们使用了ItemStyle-CssClass="iqStyle"。在WPF中应用样式同样简单;这里我们使用Style="{StaticResource FontStyle}"{...}部分利用绑定来实际应用值——StaticResource提供对先前加载资源的引用,因此在此处内联样式很有用。WPF允许你创建等同于外部样式表的样式。Josh Smith提供了关于使用外部资源的优秀教程。(我最喜欢的是这个。)

数据绑定

在这两个应用程序中,我们都使用XPath从XML中检索值。在这两种情况下,我们都创建了一个DataSource来链接到XML文件,然后说明了我们希望如何显示它。

在ASP.NET中,我们声明想要使用一组BoundField来显示数据的每个部分。

这里使用的WPF功能更强大,因为我们将项目的显示方式与其实际显示的容器分开了。这意味着我们可以在不同的容器中使用相同的模板——从而保持一致性并消除重复。在WPF代码中,模板是DataTemplate部分的内容。它表明我们希望每个项目显示一行数据,包含三列。每个项目都显示在一个TextBlock中,它是一个通用的文本类,并通过单向数据绑定绑定到特定元素。

在我们的示例中,DataTemplate的实际使用者是ListBoxItemsSource告诉运行时我们想将数据源中的数据绑定到我们的列表框。如前所述,DataTemplate中的Grid代表一行数据。ItemTemplate简单地告诉应用程序为每一行应用哪个模板,并且在某种程度上,可以认为它类似于GridView上的RowDataBound方法。因此,对于每一行数据,我们将创建一个由PersonTemplate表示的Grid。

结论

我希望这篇文章能让你对WPF产生足够的兴趣,让你想开始尝试。如果你有ASP.NET的经验,那么WPF的某些元素会更容易理解。WPF背后的团队显然从ASP.NET中学到了很多经验,并将其运用得很好。通过从ASP.NET中应用程序开发的角度来思考WPF元素,许多概念将突然变得清晰起来。显然,我省略了很多关于如何使用WPF的细节,而且我并不是说WPF应该用于Web开发,但它展示了那种特定的思维方式可以给你一个良好的开端。

可能,你将面临的最大的初步障碍是熟悉WPF如何利用绑定,这远远超出了仅仅绑定到数据库中的项。一旦你开始欣赏它如何让你绑定到应用程序中的几乎任何东西,你就会意识到你可以在不编写任何C#(或VB.NET)的情况下完成多少工作。

推荐阅读

我不会链接到文章,但我可以建议你阅读Josh SmithKarl ShiflettSacha Barber的WPF文章吗?他们创作了一些很棒的教程,适合所有水平的读者。

© . All rights reserved.