动手试验:显示示例 SQL 数据库中的数据
在 Microsoft Expression Blend 中,可以使用 XML 数据源和公共语言运行时 (CLR) 对象数据源。XML 数据源很容易使用,而 CLR 对象数据源则复杂得多。下列过程介绍了如何在 Expression Blend 应用程序中显示来自 CLR 数据源的数据。前两项任务是从示例数据库中获取数据并将数据转换为 Expression Blend 可以绑定到的格式。第三项任务是创建 Expression Blend 项目,使其包含绑定到数据的对象。
![]() |
---|
对于 Microsoft Silverlight 应用程序,请参阅 MSDN 上的 Silverlight 数据绑定 |
![]() |
---|
若要按照本主题中提供的操作步骤执行操作,必须安装 Microsoft Visual Studio 2010 和带有 AdventureWorks 示例数据库的 Microsoft SQL Server 2008。有关如何获取 AdventureWorks 示例的详细信息,请参阅 MSDN 上的安装 AdventureWorks 示例数据库和示例 如果您愿意,也可以从其他数据库创建 DataTable 或 DataSet 。如果这样做,则可以调整本主题中的第一项和第二项任务中的操作,以适合您所使用的数据。只要使用的是 CLR(或 Microsoft .NET Framework)数据源,基本原理将是一样的。 |
定义并填充 DataTable
以下过程说明如何在 Visual Studio 2010 中创建类库,以使用 AdventureWorks 示例数据库中的数据来填充 DataTable 的实例。
在 Visual Studio 2010 的“文件”菜单上,指向“新建”,然后单击“项目”。
在“新建项目”对话框中,单击“项目类型”下的“Visual C#”。在“模板”下,单击“类库”。将新项目命名为“AWDataSource” ,然后单击“确定”。
Visual Studio 将为新类库项目生成代码,并打开 Class1.cs 文件以供编辑。
在“Class1.cs”文件中,将公共类定义的名称从“Class1”改为“ProductPhotosCollection” **** (此名称更直观)。
在“解决方案资源管理器”中,右键单击所需项目的名称(“AWDataSource”),指向“添加”,然后单击“新建项”。
在“添加新项”对话框中,从模板列表中选择 DataSet ,将该项命名为 ProductPhotos.xsd ,然后单击“添加”。
将以架构文件和支持类文件的形式向项目中添加一个数据集。另外,还将打开架构文件以供编辑。
注意:
DataSet 是一个包含数据表的对象,您可以将内存中的数据临时存储在这些数据表中以便运行应用程序。有关详细信息,请参阅 MSDN 上的“Visual Studio 中的数据集”概述
。
在“服务器资源管理器”中,右键单击“数据连接”,然后单击“添加连接”。
在“选择数据源”对话框中,“数据源”字段应该已经列出“Microsoft SQL Server (SqlClient)”。
提示:
如果不打算使用 SQL Server 数据库,请单击“更改”按钮以选择备用的数据源。下列步骤将与 Visual Studio 的“选择数据源”对话框中显示的内容不匹配。
在“服务器名称”字段中,输入安装了 AdventureWorks 数据库的 SQL Server 实例的名称。
提示:
如果打算使用不同于 AdventureWorks 数据库的 SQL Server 数据库,请选择安装了所需 SQL Server 数据库的服务器的名称。
在“登录到服务器”下,选择登录到 SQL Server 实例所需的身份验证方法。可能必须与服务器管理员联系,以获取该信息。“Windows 身份验证”使用当前的登录凭证。“SQL Server 身份验证”需要已配置为具有数据库的访问权限的帐户的用户名和密码。
在“连接到一个数据库”下,选择 AdventureWorks 数据库。只有在登录凭证正确、计算机上安装了 AdventureWorks 数据库并且计算机正在运行 SQL Server 时,该数据库才会显示。
单击“测试连接”按钮。如果测试连接不成功,请向 SQL Server 管理员寻求帮助。
单击“确定”以完成数据库连接的创建过程。在“服务器资源管理器”中,新的连接显示在名为“<servername>.AdventureWorks.dbo”的“数据连接”节点之下,其中的 <servername> 为服务器的名称。
在“服务器资源管理器”中,依次展开新的“<servername>.AdventureWorks.dbo”连接节点和“表”节点,然后找到“ProductPhoto”表。在设计图面上打开 ProductPhotos.xsd 文件,然后将“ProductPhoto”表从“服务器资源管理器”拖到设计图面上。此时已创建一个可以连接到 AdventureWorks 数据库并返回“ProductPhoto”表的内容的类型化数据集。
在 Class1.cs 文件的“ProductPhotosCollection”类中添加以下方法:
private void GetData() { ProductPhotosTableAdapters.ProductPhotoTableAdapter da = new ProductPhotosTableAdapters.ProductPhotoTableAdapter(); ProductPhotos.ProductPhotoDataTable dt = da.GetData(); }
“ProductPhotosTableAdapters”命名空间在 ProductPhotos.Designer.cs 文件中定义,而该文件在您创建 ProductPhotos DataSet 时由 Visual Studio 生成。此时已创建一个方法,在应用程序运行时,该方法会用数据填充 ProductPhotos DataTable 的实例。
(按 Ctrl+Shift+B)生成项目以确保其中不包含任何错误。
将数据集合调整为 WPF 集合
以下过程说明如何在 Visual Studio 2010 中创建一个类库,以将来自 DataTable 的数据转换为 ObservableCollection ,以便 Expression Blend(或任何使用 Windows Presentation Foundation (WPF) 的应用程序)能够绑定到这些数据。将定义“ProductPhoto”类以表示表行中的数据,并将“ProductPhoto”的集合作为私有成员添加到“ProductPhotosCollection”中,然后添加一个公开访问器( get 方法),以便类外部的代码能够访问该私有成员。
![]() |
---|
如果执行了本主题中的前一过程,现在可以使用 DataTable 实例,该实例包含来自 AdventureWorks 数据库的“ProductPhoto”表的数据。如果具有使用其他源的数据填充的 DataTable 或 DataSet ,则可以调整下列步骤中的数据表名称和字段名称,以便与所使用的数据相符。 |
在 Visual Studio 2010 中,右键单击“解决方案资源管理器”中的所需项目名称,然后单击“添加引用”。在“.NET”选项卡上,选择 WindowsBase 程序集。如果未列出 WindowsBase 程序集,请单击“浏览”选项卡,并在 %SystemDrive%\Program Files\Reference Assemblies\Microsoft\Framework\v3.0 文件夹中找到 WindowsBase.dll 程序集。
单击“确定”。 WindowsBase 程序集实现了 System.Collections.Object.ObservableCollection 类。
在 Class1.cs 文件的顶部,添加以下语句:
using System.Collections.ObjectModel;
仍然在 Class1.cs 文件中,将以下“ProductPhoto”类定义添加到“AWDataSource”命名空间,从而获得要使用的类:
public class ProductPhoto { }
在“ProductPhotosCollection”类中添加以下成员:
private ObservableCollection<ProductPhoto> productPhotos = new ObservableCollection<ProductPhoto>();
在“ProductPhotosCollection”类中添加以下访问器方法:
public ObservableCollection<ProductPhoto> ProductPhotos { get { return this.productPhotos; } }
接下来的步骤会将 ID、修改日期和两幅照片从 DataTable 复制到 ObservableCollection 。
在“解决方案资源管理器”中,右键单击所需的项目名称,然后单击“添加引用”。添加对 PresentationCore 程序集的引用。
在 Class1.cs 文件顶部,添加下列语句:
using System.Windows.Media; using System.Windows.Media.Imaging;
在“ProductPhoto”类中添加成员,使该类如下所示:
public class ProductPhoto { // Public Accessors to the private properties. public int ID { get { return id; } } public ImageSource ThumbNailPhoto { get { return thumbNailPhoto; } } public ImageSource LargePhoto { get { return largePhoto; } } public DateTime ModifiedDate { get { return modifiedDate; } } // Constructor. public ProductPhoto(int id, byte[] thumbNailPhoto, byte[] largePhoto, DateTime modifiedDate) { this.id = id; this.thumbNailPhoto = ByteArrayToImageSource(thumbNailPhoto); this.largePhoto = ByteArrayToImageSource(largePhoto); this.modifiedDate = modifiedDate; } // Private properties. private int id; private ImageSource thumbNailPhoto; private ImageSource largePhoto; private DateTime modifiedDate; // Supporting method. private ImageSource ByteArrayToImageSource(byte[] data) { BitmapImage image = null; if (null != data) { image = new BitmapImage(); image.BeginInit(); image.StreamSource = new System.IO.MemoryStream(data); image.EndInit(); } return image; } }
在“ProductPhotosCollection”类中的“GetData”方法末尾添加以下代码,以便该方法将“DataTable”复制到“ObservableCollection”:
productPhotos.Clear(); foreach (ProductPhotos.ProductPhotoRow row in dt) { productPhotos.Add(new ProductPhoto( row.ProductPhotoID, row.ThumbNailPhoto, row.LargePhoto, row.ModifiedDate)); }
此时,作为触发 ProductsPhotosCollection.GetData 方法的一种简便方法,可以实现一个 Command 。
在“文件”菜单上,单击“新建项”。在“新建项”框中,单击“类”。在“名称”框中,键入 DelegateCommand.cs 。
在新的页面中,按 Ctrl+A 选择所有内容,然后按 Delete。复制以下代码,然后将它们粘贴到您刚创建的页面中。
namespace AWDataSource { using System; using System.Windows.Input; /// /// DelegateCommand is a simplified version of ICommand in WPF. You can wrap one of these around any method, /// and thus bind any command on any WPF object to your method. /// /// DelegateCommand also supports an IsEnabled property that you can use to turn the command on and off. /// public sealed class DelegateCommand : ICommand { // Type signature of the method that DelegateCommand works with - returns void, no arguments. public delegate void SimpleEventHandler(); // Remember the method so that it can be called at the right time. private SimpleEventHandler handler; // Maintain the enabled state. private bool isEnabled = true; // Simple constructor: Pass in the method that needs to be called when the command executes. public DelegateCommand(SimpleEventHandler handler) { this.handler = handler; } #region ICommand implementation // Executing the command is as simple as calling the method. void ICommand.Execute(object arg) { this.handler(); } // Saying whether the command can be executed. ICommand.CanExecute(object arg) { return this.IsEnabled; } // This is the event that the command architecture of WPF listens to so it knows when to update // the UI on command enable/disable. public event EventHandler CanExecuteChanged; #endregion // Public visibility of the isEnabled flag - note that when it is set, the event must be raised // so that WPF knows to update any UI that uses this command. public bool IsEnabled { get { return this.isEnabled; } set { this.isEnabled = value; this.OnCanExecuteChanged(); } } // Simple event propagation that makes sure that someone is listening to the event before raising it. private void OnCanExecuteChanged() { if (this.CanExecuteChanged != null) { this.CanExecuteChanged(this, EventArgs.Empty); } } } }
在“文件”菜单上,单击“保存”。
DelegateCommand.cs 文件中的代码可用于将任何命令绑定到您的方法。
在 Class1.cs 文件中,向“ProductPhotosCollection”类中添加以下成员:
private DelegateCommand getDataCommand;
在“ProductPhotosCollection”类中添加以下构造函数以初始化该命令:
public ProductPhotosCollection() { getDataCommand = new DelegateCommand(delegate() { GetData(); }); }
最后,向“ProductPhotosCollection”类中添加以下访问器方法以公开该命令:
public DelegateCommand GetDataCommand { get { return getDataCommand; } }
(按 F5)生成项目以确保其中不包含任何错误。现在已创建一个类,您可以在 Expression Blend(或任何 WPF)应用程序中将其用作数据源。此类可以是“ProductPhotosCollection”,也可以是用户自己定义的相似类。
在 Expression Blend 中向数据源绑定过程
以下过程说明如何创建一个非常简单的 Expression Blend 应用程序,该应用程序包含一个绑定到数据源的 ListBox 控件。该应用程序使用一种称为“列表-细节” ** 视图的常见用户界面设计模式。左侧的窗格称为“列表窗格” ** ,其中包含产品列表。只要在此窗格中选择一个产品,该产品的相关详细信息就会显示在右侧的窗格(称为“细节窗格” ** )中。在一个窗格中选定某个对象时更新另一个窗格的内容是通过控件之间的“数据同步” ** 实现的。
在 Expression Blend 中,单击“文件”,然后单击“新建项目”。
在“新建项目”对话框中,选择“WPF 应用程序”项目类型。这将创建基于 Windows 的应用程序项目。这种应用程序可在设计的过程中进行生成和运行。另一个选项是“WPF 控件库”项目,该项目可用于设计供在其他基于 Windows 的应用程序中使用的控件。
在“名称”文本框中,键入“AWProductPhotos” 。将“语言”设置保留为默认值,因为在此过程中不需要编写任何代码。
单击“确定”。Expression Blend 将加载新项目,并显示该项目以供编辑。
提示:
如果已经打开一个项目,则可能会先显示一个对话框,询问在打开新项目之前是要保存还是放弃当前项目。
在将新项目加载到内存中之后,请单击“文件”菜单上的“全部保存”以将该项目保存到磁盘上。“名称”文本框应该已经包含名称“AWProductPhotos”,因此请单击“确定”。
小心:
在 Expression Blend 中工作时,所做的更改不会自动保存到硬盘,因此一定要尽早且经常手动保存文件。有关详细信息,请参阅管理解决方案、项目和文件。
在“项目”菜单上,单击“添加引用”。
在“添加引用”对话框中,浏览到在本主题中的第二项任务结束时生成的 AWDataSource.dll 文件,以添加对该文件的引用。AWDataSource.dll 文件可能位于 AWDataSource 项目的 bin/Debug 文件夹中。
单击“确定”。AWDataSource.dll 此时已成为项目的一部分。如果在“项目”面板中展开“引用”节点,您将看到对 AWDataSource.dll 的引用。
在“数据”面板中,单击“创建数据源”
,然后单击“创建对象数据源”。
在“创建对象数据源”对话框中,展开“AWDataSource”节点,选择“ProductPhotosCollection”,然后单击“确定”。
在“数据”面板中,已向项目中添加名为“ProductPhotosCollectionDS”的数据源。“ProductPhotosCollectionDS”数据源表示所引用的 CLR 类的实例的结构。依次展开“ProductPhotosCollectionDS”和“ProductPhotosCollection”可查看相应的结构。在本任务的后续步骤中,您会将数据从“数据”面板中拖到美工板上,以创建新控件。
在“对象和时间线”面板中,单击 LayoutRoot 以将其激活。请注意,在激活该对象时,其名称周围会显示底纹范围框。
提示:
如果要向某个对象添加子对象或者执行其他特殊操作,请在“对象和时间线”面板中双击父对象,然后添加子对象。此操作称为“激活” 。激活的对象由其对象名称周围显示的底纹范围框标识。
如果要更改某个对象的属性,请在“对象和时间线”面板中单击相应的对象名称。此操作称为“选定” 。选定的对象由突出显示的背景颜色标识。
可以选定对象而不激活它。
在“工具”面板中,单击“选择”
。在美工板上,将指针移到 LayoutRoot 顶部的宽标尺区域上。将出现一个列标尺跟随鼠标指针移动,以指示在单击时将放置新的列分隔线的位置。
单击以创建新的列分隔线,使左右两侧的列大致等宽。左侧的列将包含产品照片缩略图的列表,而右侧的列将包含表示选定列表项的大照片。 LayoutRoot 中将显示一条列分隔线。
提示:
若要能够在美工板上查看完整的 LayoutRoot 对象,可能需要执行缩小操作。若要缩小,请在美工板底部的文本框
中输入一个缩放值,单击缩放值旁边的箭头,或者按住 Ctrl 键并旋转鼠标滚轮。
在美工板上,将指针移到 LayoutRoot 左侧的宽标尺区域上。单击以创建一个新的行分隔线,使顶部的行大到足够容纳按钮。单击顶部行旁边显示的打开的挂锁图标
,将该行锁定为固定高度。
提示:
若要查看上一步中所述操作的结果,请在“对象和时间线”面板中右键单击 LayoutRoot ,然后单击“查看 XAML”(以查看可扩展应用程序标记语言或 XAML)。这会将美工板切换到“XAML”视图,并突出显示 LayoutRoot 代码。若要更好地进行查看,请在“窗口”菜单上单击“隐藏面板”(按 F4 或 Tab)。
表示 LayoutRoot 的
<Grid>
对象中已添加<Grid.ColumnDefinitions>
部分和<Grid.RowDefinitions>
部分。“Width”和“Height”属性使用 星号大小定义 ,这意味着各个列的大小会保持它们之间的相对比例。例如, Width 为 2* 所产生的列的大小是宽度设为 * 的列的两倍。锁定的行不使用星号大小定义,因为它的高度是固定的。查看完 XAML 代码之后,记住要切换回“设计”视图并还原隐藏的面板(按 F4 或 Tab 键)。
在“数据”面板中,将 GetDataCommand 从“ProductPhotosCollection”下拖到美工板左上角的网格单元格中。
在“工具”面板中,双击“按钮”以在美工板上绘制按钮。在显示的下拉列表中,单击“Button”。
在“创建数据绑定”对话框的“属性”下拉列表中,选择“命令”,然后单击“确定”。此操作将会创建一个新按钮,并将其绑定到“AWDataSource”类中的 GetDataCommand 访问器方法。在运行时,如果单击该按钮,则会对“ProductPhotosCollection”数据源执行 GetDataCommand ,而且,与本主题中的第二项任务一样,该命令的实现要调用 GetData 方法。
提示:
通过单击“工具”面板中的“选择”工具,并在美工板上或在“对象和时间线”面板中选择新按钮,然后在美工板上使用修饰工具,可以在美工板上移动新按钮并重设其大小。有关详细信息,请参阅重定位或转换对象和调整对象大小或缩放对象。
提示:
可以在“属性”面板访问数据绑定。若要在创建数据绑定之后重新打开“创建数据绑定”对话框,请先在“对象和时间线”面板中选择“Button”,然后,在“属性”面板中的“杂项”下,单击“Command”属性旁边的“高级选项”
,再单击“数据绑定”。
在“对象和时间线”面板中选择 [Button] ,然后在“属性”面板的“公共属性”下查找 Content 属性。通过输入文本 获取产品照片 来设置 Content 属性,然后按 Enter。
通过单击“工具”面板中的“选择”工具,然后在美工板上使用修饰工具,可以移动 [Button] 对象并重设其大小。使 [Button] 适合左上角的网格单元格。然后,在“属性”面板中的“布局”下,设置下列属性:
将 Width 和 Height 属性设置为 Auto 。
将 Margin 属性设置为 0 。
将 HorizontalAlignment 和 VerticalAlignment 属性设置为 Center 。
这些设置将确保该按钮的大小刚好能够容纳 Content 属性中的文本,而且还使该按钮在网格单元格中居中显示。
在“数据”面板中,将“ProductPhotos (数组)”拖到美工板左下角的网格单元格中。
在“创建数据绑定”对话框的“属性”下拉列表中,选择 ItemsSource ,然后单击“确定”。
提示:
从本质上来说,“数据模板” 是可包含数据绑定的 UI 对象树。每当需要显示特定类型的数据时,将会选择适当的数据模板,而选定的模板会设置其对象树的新副本的格式,并使用更新的数据显示给用户。 ListBox 对象中显示的每一项都是本主题的第二项任务中实现的“ProductPhoto”类型的对象。
在“创建数据模板”对话框中,选中“新建数据模板和显示字段”单选按钮。此选项定义从“数据”面板拖动的数据类型的结构(例如,“ProductPhoto”对象集合中的每个对象)。现在可绑定到数据结构的任何部分,从而定义数据模板的对象树的外观。在每个数据项旁边都有一个下拉列表,可确定将用于显示数据字段的对象( StackPanel 和 TextBlock 对象)。在下拉列表旁边是一个标签,可指明数据项将绑定到对象的哪些属性。
清除“LargePhoto”选项,因为只需要在 ListBox 中显示它。
“ModifiedDate”数据字段当前的类型为 StackPanel ,但必须将该控件更改为更适合显示该数据类型的对象类型。在“ModifiedDate”旁边的下拉列表中,选择 TextBlock 。标签将自动变为 Text 。
“ThumbNailPhoto”数据字段当前的类型为 ImageSource ,但必须将该控件更改为更适合显示该数据类型的对象类型。在“ThumbNailPhoto”旁边的下拉列表中,选择 Image 。标签将自动变为 Source 。
单击“确定”。此操作将在文档中插入新的 ListBox 。
提示:
数据模板是一种资源。若要在创建“ProductPhotosTemplate”数据模板之后对其进行修改,请在“资源”面板中展开“Window1.xaml”节点,展开“Window”,然后单击“ProductPhotosTemplate”旁边的按钮。
在“对象和时间线”面板中选定 [ListBox] 对象,然后在“属性”面板中的“布局”下执行下列操作:
将 Width 和 Height 属性设置为 Auto 。
将 Margin 属性设置为 8 。
将 HorizontalAlignment 和 VerticalAlignment 属性设置为 Center 。
这些设置将确保 ListBox 几乎能够完全填满左下角的网格单元格。
在“工具”面板中,选择 Image
。
提示:
如果“工具”面板中没有显示 Image 控件,则可以通过单击“资产”
来查找该控件。从此库中选择某个控件之后,其图标将显示在“工具”面板中的“资产”按钮下方。
在美工板上右下角的网格单元格中,绘制一个新的 Image ,使其几乎填满整个单元格。
在“对象和时间线”面板中选择 [Image] ,然后在“属性”面板的“公共属性”下查找 Source 属性。单击 Source 属性的名称,然后从显示的下拉列表中选择“数据绑定”。
由于要将数据绑定到 [ListBox] 对象的属性,因此在“创建数据绑定”对话框中选择“元素属性”选项卡。
在“场景元素”下,展开“Window”和 LayoutRoot ,然后选择 ListBox ( [System.WIndows.Controls.ListBox] )。
在“显示”下拉列表中,选择“所有属性”。这将显示可以绑定到的所有属性,而不仅是显示与 Source 属性具有相同数据类型 ( String ) 的属性。
在“属性”下,选择 SelectedItem : (Object) 。
选中“使用自定义路径表达式”复选框。默认表达式为 SelectedItem 。将它改为 SelectedItem.LargePhoto ,以便绑定到当前选定的 ProductPhoto 对象的 LargePhoto 成员。
单击“完成”。
在“项目”菜单上,单击“测试项目”(或者按 F5)。当应用程序启动之后,单击“获取产品照片”以测试应用程序。当列表框加载了数据之后,逐个查看每一项并验证显示在右侧列中的大照片。
完成的应用程序
Microsoft Corporation 版权所有 ⓒ 2011。保留所有权利。