WCF Ria Services(通常称为RIA服务),专门设计让Silverlight应用程序访问数据库,网上有关其示例应用都是基于简单的数据显示,其中MSDN网站上有详细的解决方案介绍,地址http://msdn.microsoft.com/zh-cn/library/ff713719(v=vs.91).aspx,我认为把这个看懂后,你基本上就入门了。
但是由于项目需要,我要把SQL SERVER数据库中以二进制流保存的图片显示到客户端浏览器里,在网上找了很久的资料,都没找到相关的介绍,最后花了不少功夫,终于实现了功能。先看其效果如下:
在数据库中,我们建了一个ImageTable数据库,两列数据ImageId(int)和ImageData(varbinary(MAX)),然后通过下面命令插入初始数据和图片
Use ImageDB; Go INSERT INTO ImageTable VALUES (1,(SELECT * FROM OPENROWSET(BULK N'D:\DEC.jpg',SINGLE_BLOB) AS Photo))
然后新建一个silverlght业务应用程序,添加一个显示此图片的silverlight页,ADO.NET实体数据模型和域服务类,过程可参考前面给出的例子,这里主要说明如何把图片显示出来。
<navigation:Page xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="ImageTestApp.Views.WorkerImage" 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/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:local="clr-namespace:ImageTestApp.Views" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth=" Title="WorkerImage Page"> <navigation:Page.Resources> <local:DataToImageConverter x:Key="DataToImageConverter"></local:DataToImageConverter> </navigation:Page.Resources> <Grid x:Name="LayoutRoot"> <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" > <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock Text="图片" Style="{StaticResource HeaderTextStyle}"/> <sdk:DataGrid AutoGenerateColumns="> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn Header="序号" Binding="{Binding ImageId}" /> <sdk:DataGridTemplateColumn Header="图片" CanUserResize="False" > <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <!--<TextBox x:Name="imgLogo" Text="{Binding Path=ImageData}" > </TextBox>--> <Image x:Name=" Source="{Binding Path=ImageData,Converter={StaticResource DataToImageConverter}}" > </Image> </StackPanel> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> </sdk:DataGrid.Columns> </sdk:DataGrid> </StackPanel> </ScrollViewer> </Grid> </navigation:Page>
注意,我们在datagrid前两行定义了两列,序号和图片,由于ImageData是二进制流,无法在图片控件上直接显示,所以图片显示一栏还需要个转化器,下面是后台代码。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Navigation; using System.Windows.Data; using System.Windows.Media.Imaging; using System.IO; using System.Text; using ImageTestApp.Web; using System.ServiceModel.DomainServices.Client; namespace ImageTestApp.Views { public partial class WorkerImage : Page { OrganizationContext _OrganizationContext = new OrganizationContext(); public WorkerImage() { InitializeComponent(); this.dataGrid1.ItemsSource = _OrganizationContext.ImageTables; _OrganizationContext.Load(_OrganizationContext.GetImageTableQuery()); } } public class DataToImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { BitmapImage bi = new BitmapImage(); bi.SetSource(new MemoryStream((byte[])value)); Image image = new Image(); image.Source = bi; return bi; //Image image = new Image(); //image.Source = bi; // return image; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
由于界面里用的Image控件绑定图片,所以刚开始在转换器里需要返回Image类型数据,但实际上此方法行不通,最后看了Image.Source属性才知道应该返回BitmapImage类型,下面是Image的用法:
<Image Width="200" Margin="5" Grid.Column="1" Grid.Row="1" > <Image.Source> <BitmapImage UriSource="sampleImages/bananas.jpg" /> </Image.Source> </Image>
通过此转换器,我们就能将接收到的二进制流转换为图片。如果不通过转换,直接利用datagrid的自动显示功能,图片一栏将显示System.Byte[],让人搞不清楚。此项目还需要完成图片上传功能,后面再加上。
其实在调试过程中,我还有点不明白的是 dataGrid1.ItemsSource 一直看不到接收到的数据,但是客户浏览器里确实已经有了已经有了数据库中的每一项列表。