I:项目描述:利用 Silverlight+WCF 技术,模拟资源管理器(如图1)功能,通过地址栏输入本地文件夹路径,然后将解析出来的该目录下所有文件(夹)存储到数据库中,然后再加载到界面上显示出来;

(图1)

II:涉及技术:Silverlight + WCF + Component One 控件(TreeView 和 FlexGrid)
III:开发环境:Visual Studio2012 + SQL Server 2008 R2 + Silverlight 5 + Component One C1Silverlight_2014v1;

一  项目架构(如图2)

(图2)

FolderDB:DAL(数据访问层),包括文件属性类 Folders,文件夹树模型类 FolderModel,数据库操作类 DBHelper;

FolderUI:Silverlight 客户端,基本界面显示,包括 FlexGrid 标题数据源类 ColumnHeaders,文件大小值转换类 FileSizeConverter;

FolderWCF:WCF 服务层,包括 FolderService 服务类;

FolderWeb:Web层,该项目中涉及不多;

二  源码部分解析

 /// <summary>
/// 执行多条SQL语句,实现数据库事务
/// </summary>
/// 多条SQL语句
public int ExecuteSqlTran(List sqlStrList)
{
SqlTransaction sqlTran = null;
try
{
if (ConnectionState.Open != m_SqlConn.State)
{
m_SqlConn.Open();
}
int count = 0;// 影响的记录数
SqlCommand cmd = new SqlCommand();
sqlTran = m_SqlConn.BeginTransaction();
cmd.Connection = m_SqlConn;
cmd.Transaction = sqlTran;
foreach (string sqlStr in sqlStrList)
{
if (sqlStr.Trim().Length > 1)
{
cmd.CommandText = sqlStr;
count += cmd.ExecuteNonQuery();
}
}
sqlTran.Commit();// 提交数据库事务
return count;
}
catch (SqlException sqlEx)
{
if (null != sqlTran)
{
sqlTran.Rollback();// 失败后回滚
} throw new Exception(sqlEx.Message);
}
}

注意执行完 ExecuteNonQuery() 后,并不算完,事务在最后还需要进行提交数据库事务才行,sqlTran.Commit(),否则操作一直都不会执行,但是调试过程中也不会出现异常;

 public class FolderModel
{
/// <summary>
/// 当前目录(文件夹)属性
/// </summary>
public Folders CurrFolder { get; set; } /// <summary>
/// 子文件(夹)集合
/// </summary>
public ObservableCollection SubFolders { get; set; } public FolderModel()
{
SubFolders = new ObservableCollection();
} public FolderModel(Folders folders)
{
CurrFolder = folders;
SubFolders = new ObservableCollection();
}
}

这是绑定 C1TreeView 控件的数据源模型,其中 ObservableCollection 是表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。SubFolders 则是作为子树的绑定,CurrFolder 则是作为当前节点的绑定,详细见下面的 XAML 代码解释;

 /// <summary>
/// Header数据源
/// </summary>
public class ColumnHeader : INotifyPropertyChanged
{
private List m_HeaderList;
public event PropertyChangedEventHandler PropertyChanged;
public List HeaderList
{
get
{
return m_HeaderList;
}
set
{
m_HeaderList = value;
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("HeaderList"));
}
}
}
}

该类作为 C1FlexGrid 列标题即 Column.Header 的动态绑定数据源,HeaderList 中存储的是每列的列名;该数据会从 WCF 服务端获取,然后绑定在客户端上显示;

 public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
int byteSize = int.Parse(value.ToString());// 单位字节
int nKBSize = (int)Math.Ceiling(byteSize * 1.0 / 1024);// 转换成KB return string.Format("{0} KB", nKBSize);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

因为要将文件大小该列的值全部由字节转换成 KB,则将 Size 那一列绑定该转换器即可;

  • ItemsSource="{Binding SubFolders}" // 绑定 SubFolders 数据源,该数据源在 FolderModel 类中定义,作为树数据源;
  • ItemTemplate="{StaticResource FolderTemplate}" // 指定树每个节点的模版定义;静态资源 FolderTemplate 则是在<UserControl.Resources>标签中定义;
  • HierarchicalDataTemplate:// 定义 TreeView 节点模版
  • ItemsSource="{Binding SubFolders}" // 同样指定该模版数据源
  • <TextBlock Text="{Binding CurrFolder.Name}" /> // 节点所包含的内容,绑定 CurrFolder 对象中 Name 属性值,在 FolderModel 类中定义;

C1FlexGrid控件:
AutoGenerateColumns="False" //绑定数据源中有些列数据并不想显示出来,只要求部分指定的列显示,则需要设置成 false,阻止其自动生成列;

<c1:C1FlexGrid.Columns> // 设置每列所绑定的数据

 <c1:Column Binding="{Binding [2]}" HorizontalAlignment="Left" Width="200">
<c1:Column.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=HeaderList[2]}" />
</DataTemplate>
</c1:Column.HeaderTemplate>
</c1:Column>

该树绑定的数据源类型为 List<List<string>>,所以 Binding 的对象就是 List<string> 类型,而按以往的思路,Binding 的对象是具有 get,set 的属性,查看了 List 类下有 public T this[int index] { get; set; },所以可以直接通过 [n] 索引来绑定数据;

HeaderTemplate 作为 Header 的模版定义,绑定的数据源类型是 ColumnHeader,直接访问其属性 HeaderList 即可;

添加文件夹树节点单击事件,在 FlexGrid 中加载该文件夹下所有文件信息;

 // 文件夹目录上的选择单个文件夹事件
private void FoldersTree_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
C1TreeViewItem selectedNode = tvFoldersTree.SelectedItem;
if (null != selectedNode)
{
// 当前选择的节点
FolderModel selectedFolderModel = (FolderModel)selectedNode.Header;
m_SelectedFolderName = selectedFolderModel.CurrFolder.Name;// 节点名称(文件夹名)
m_WCFClient.GetFilesAsync(selectedFolderModel.CurrFolder.ID);
}
} void GetFilesCompleted(object sender, GetFilesCompletedEventArgs e)
{
if (null == e.Error)
{
List<List<string>> result = e.Result;
ColumnHeader columnHeader = new ColumnHeader();
columnHeader.HeaderList = result[0];
fgFilesView.ColumnHeaders.DataContext = columnHeader;// 绑定列标题数据源 result.RemoveAt(0);// 移除第一个表示列名称的List
fgFilesView.ItemsSource = new PagedCollectionView(result);// 绑定列内容数据源
fgFilesView.Columns[3].ValueConverter = new FileSizeConverter();
txtMsg.Text = "加载文件夹【" + m_SelectedFolderName + "】目录下的文件已完成。";
}
else
{
txtMsg.Text = "加载文件数据失败,异常信息:" + e.Error.Message;
}
}

C1TreeView 的节点是 C1TreeViewItem 类型,所以获得当前点击的节点可以用:C1TreeViewItem selectedNode = tvFoldersTree.SelectedItem;  当然也可以由 sender 转型得到;值得注意的是,在这里,C1TreeViewItem 的 Header 属性是 C1TreeView 所绑定数据源的类型,即 FolderModel,而在 xaml 文件中,对 Column 标签的 header 属性进行值绑定时,其 header 值为 string 类型!!故在 xaml 中对 header 的绑定是通过 HeaderTemplate 模版定义来完成的;

服务器端返回的 e.Result 是一个 List<List<string>> 类型,其中第一个 List<string> 指的是列名;列名的绑定方式:fgFilesView.ColumnHeaders.DataContext = columnHeader;  C1FlexGrid 的绑定方式:fgFilesView.ItemsSource = new PagedCollectionView(result);  其中 DataContext 和 ItemsSource 两种是有区别的,本人还没有学习到,读者可以阅读他人的相关博文学习;

对第三列的文件大小需要绑定值转换器:fgFilesView.Columns[3].ValueConverter = new FileSizeConverter(); 即可;

 <configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFolderService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:54416/FolderService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IFolderService"
contract="FolderServiceRefer.IFolderService" name="BasicHttpBinding_IFolderService" />
</client>
</system.serviceModel>
</configuration>

ServiceReferences.ClientConfig

该文件是由 Silverlight 客户端添加服务引用时自动生成的配置文件,其中 <bindings> 标签内容是由 WCF 服务器端的 Web.config 配置文件中对应的 <bindings> 标签内容截取部分而来,对于 maxBufferSize 和 maxReceivedMessageSize 两个属性最好设置值大一些,而且必须值一样,不能超过 2147483647;否则会报如下异常:

1:“由于正在缓冲消息,MaxReceivedMessageSize 和 MaxBufferSize 的值必须相同”;

2:发生了 System.ServiceModel.ProtocolException

Message=已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的MaxReceivedMessageSize属性。

Source=System.ServiceModel

StackTrace:

在System.ServiceModel.Channels.HttpInput.ThrowHttpProtocolException(String messagem, HttpStatusCode statusCode, String statusDescription)

<endpoint> 是客户端终结点设置,address 属性指 WCF 所在服务器端的访问路径,其他属性内容也是从服务器端 Web.config 配置文件中自动生成过来的;

三  项目遇到的问题及参考解决方法

1:WCF 的独立调试

参考解决方法:将 WCF 项目“设为启动项目”,并将 svc 文件“设为起始页”,然后按“F5”即可打开“WCF测试客户端”,如下图,然后选择要是调试的方法(如SaveFolders()),在右侧的“值”中填入所需参数(字符串里需要转义),再执行“调用”即可在“响应”中看到结果值;如果在 VS 中相应的方法中加入断点,则可以进行断点调试操作!

2:WCF 测试客户端的配置文件

参考解决方法:上图中,在“配置文件”上右键选择“用 SvcConfigEditor 进行编辑”选项,即可对 WCF 测试客户端的配置文件进行修改;

尤其是出现“已超过传入消息(65536)的最大消息大小配额。”的异常信息时,需要修改其中“绑定”目录下已定义的 basicHttpBinding 属性配置信息,将其中的 MaxBufferPoolSize 和 MaxBufferSize 和 MaxReceivedMessageSize 的值均改为 int 的 MaxValue 即可;

还有,每次打开该 SvcConfigEditor,程序都会自动重新加载“个人文件夹\AppData\Local\Temp\Test Client Projects\11.0\f868aff1-aa2d-4418-abaf-f4be03a71529”下的 Client.dll.config 配置文件,f868aff1-aa2d-4418-abaf-f4be03a71529 这个根据情况会有所变动,这样之前的属性配置修改就白搭了,每次启动都要修改,这丫的肯定不干了呀,在 WCF 测试客户端里,在“工具”-》“选项”中,把“始终在启动服务时重新生成配置”选项去掉就欧克了!

3:没有异常,重新生成解决方案也都成功,但是启动 Silverlight 后界面上完全空白

参考解决方法:毫无头绪的 bug 呀,而且是深藏不露的!通过启动 Web 端的界面也无法显示 Silverlight 程序,而且查看了 Silverlight 中 xaml 文件下也无异常情况,此时此刻,可以肯定的是加载 Silverlight 过程中出错了,没有正常加载Silverlight!但是又如何知道是什么 bug,什么地方出现了 bug 呢?

在 Web 项目中找到要加载 Silverlight 应用程序的 aspx 页面文件,将 onSilverlightError 该函数内的 errMsg 错误信息弹出显示即可;

这时候再根据错误提示去找度娘就简单多了,2103的错误解决如下:

由于在修改 Silverlight 客户端的命名空间时,导致项目内部没有彻底完全的修改完命名空间,才会导致2103错误;在 Silverlight 项目右键属性中,查看“启动对象”是否是修改命名空间后的选项即可;

4:在 Silverlight 客户端添加服务引用时,异常“找不到类型 Project.Web.Service,它在 ServiceHost 指令中提供为 Service 特性值,或在配置元素...”

如果,我说的是如果,你已经完全确定你的 WCF 服务完全正确,Web.config 配置里也完全正确,那这个错误只可能是因为你在 WCF 项目中编辑完服务之后,没有对 WCF 项目“重新生成”导致的!!这也提醒着大家,在项目编码过程中,每次对 WCF 项目进行编辑修改后,都要重新生成一下,并且在 Silverlight 客户端的服务上右键“更新服务引用”才行,不然你改了半天的 WCF 服务端方法,结果执行的结果依然让人寒心,那就真的寒心了... ...

5:项目的部署问题

VS 默认是采用自带的 IIS Express 来部署 Silverlight 项目以及 WCF 服务,部署后在右下角会出现如下图标和内容;

关于 IIS Express 和本地的 IIS 的区别,是一个很有意思的话题,这里就不说了,建议去看大神博客解析,会受益匪浅的。这里简单提及一些基本的关于 IIS Express 知识:

配置文件:C:\Program Files\IIS Express\AppServer\applicationhost.config

<applicationPools> 标签    ----    应用程序池配置

<add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_BIN%\config\templates\PersonalWebServer\aspnet.config" autoStart="true" />

相当于 IIS 中

<sites> 标签    ----    网站配置,每一个 <site> 子标签,代表一个网站的配置

 <site name="Development Web Site" id="1" serverAutoStart="true">
<application path="/">
<virtualDirectory path="/" physicalPath="%IIS_BIN%\AppServer\empty_wwwroot" />
</application>
<bindings>
<binding protocol="http" bindingInformation=":8080:localhost" />
</bindings>
</site>

<defaultDocument> 标签    ----    设置默认起始页

 <files>
<add value="Default.htm" />
<add value="Default.asp" />
<add value="index.htm" />
<add value="index.html" />
<add value="iisstart.htm" />
<add value="default.aspx" />
</files>

其他的可以自行了解去了!

Silverlight+WCF 部署在本地 IIS 上,需要注意事项:

1)WCF 项目和 SilverlightWeb 项目发布到 IIS 网站下的相同目录下,

2:作为第二次发布的项目,不能选择“发布前删除所有现有文件”,否则会把前一个发布的文件清除了;


3:发布目录下的配置文件 Web.config 检查一下是不是WCF项目中的配置文件,如果不是,手动粘贴过来覆盖

4:修改 ClientBin\*.xap\ServiceReferences.ClientConfig 文件中,关于WCF服务地址的终结点配置,改为本地 ip 地址;

5:应用程序“DEFAULT WEB SITE”中的服务器错误;HTTP 错误 403.14-Forbidden;Web服务器被配置为不列出此目录的内容。

因为部署的项目中没有默认的启动页面,IIS 设置的默认启动页面文档包括【“Default.htm”,“Default.asp”,“index.htm”,“index.html”,“iisstart.htm”,default.aspx】,而你部署的项目根目录下没有这些文档中的至少一个,而且,在 IIS 功能视图中的“目录浏览”设置里也禁用了,所以报此错误!解决方法自己去搞定吧!!

6:直接访问 svc 服务文件(http://192.168.0.64/FolderService.svc)报如下异常:

当前已禁用此服务的元数据发布。

如果之前在 VS 上调试一切正常,只是发布后出现这个问题,去发布目录下查看配置文件 Web.config,看是否是 WCF 项目下的那个配置文件,不是的话就手动拷贝覆盖。

否则的话就按浏览器下面出现的异常提示解决:

[SL] Silverlight + WCF Demo项目的更多相关文章

  1. [silverlight—wcf]参数:调试资源字符串不可用,秘钥和参数通常提供足够的信息用以诊断问题。

    这段时间在做一个项目,有一项需求是上传,经过思考之后,决定采取Silverlight+WCF的方式做上传操作.就在项目做完了之后,本地测试也都没问题,发布到服务器上的时候,顿时就出现故障了.在选择文件 ...

  2. silverlight wcf mvvm

    近期工作比較忙.也没有时间发表新内容,今天有点时间,就顺便写点,说说近期开发的一套系统心得. 我刚去这个公司已经将前端确定要用Silverlight,我不知道为什么要选择这个,或许是为以后转C/S系统 ...

  3. 如何使用npm构建一个react demo项目

    方法一: 1) 安装node.js环境  点我进入nodejs官网 1.1) 下载LTS(Long term support)版本,安装 1.2) 在cmd中使用以下命令查看node是否安装成功 no ...

  4. Spring AOP 切面编程实战Demo项目

    为什么会有此项目?在某日,我看博客时,看到了讲面向切面编程的内容,之前也知道spring是面向切面编程的,只是自己没有写过相关的代码,于是决定自己写一个test.但是url拦截器从外部看,和AOP有相 ...

  5. electron demo项目npm install安装失败解决办法

    electron官网提供的demo项目,在npm install 的时候总是报错显示安装失败, 解决办法:FQ即可成功安装.

  6. Spring.net的Demo项目,了解什么是控制反转

    Spring这个思想,已经推出很多年了. 刚开始的时候,首先是在Java里面提出,后来也推出了.net的版本. Spring里面最主要的就是控制反转(IOC)和依赖注入(DI)这两个概念. 网上很多教 ...

  7. Surging Demo 项目之一

    原文:Surging Demo 项目之一 开发与运行环境 IDE Visual Stadio 2017/Visual Stadio 2019 Visual Stadio Core Docker 和 D ...

  8. demo项目开发(Python+flask+mysql+redis只包含后端接口)

    [demo项目开发需求] 用户信息管理,可以注册.登录.添加用户.删除用户 注册:任何用户可以注册,对用户提交的注册信息进行校验,返回对应的信息,其中: 用户名:必填,唯一 密码:必填,只能6-12位 ...

  9. Unity3D Demo项目开发记录

    前言 经过一段时间的学习与实际开发,unity3D也勉强算是强行入门了,正所谓好记性不如烂笔头,更何况本人并非专业从事unity3D开发,会一点C#但也并不熟悉,为了避免后期遗忘,因此特意整理了一个D ...

随机推荐

  1. 基于 Jenkins 快速搭建持续集成环境

      什么是持续集成 随着软件开发复杂度的不断提高,团队开发成员间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题.尤其是近些年来,敏捷(Agile) 在软件工程领域越来越红火 ...

  2. Hadoop学习笔记—12.MapReduce中的常见算法

    一.MapReduce中有哪些常见算法 (1)经典之王:单词计数 这个是MapReduce的经典案例,经典的不能再经典了! (2)数据去重 "数据去重"主要是为了掌握和利用并行化思 ...

  3. SQL Agent服务无法启动如何破

    问题现象 从阿里云上镜像过来的一台的数据库服务器,SQL Agent服务启动不了,提示服务启动后停止.(原数据库服务器是正常的,怀疑跟镜像有关) 如下是系统日志和SQL Agent的日志 SQLSer ...

  4. VBA批量查找和复制文件

    Function findAndCopy(srcFile As String, destFile As String, cmdFile As String) Dim WSH As Object, wE ...

  5. 分辨率、DPI、PPI和屏幕尺寸,你都知道是啥么?

    分辨率.DPI.PPI和屏幕尺寸 分辨率 DPI/PPI 坑爹的屏幕尺寸 Reference 手机开发中不免会遇到分辨率.DPI.PPI和屏幕尺寸等术语,那就弄弄清楚这些概念的真正含义. 分辨率 分辨 ...

  6. Mongoose Schemas定义中timestamps选项的妙用

    在Node.js中使用MongoDB少不了Mongoose. 假设有如下Mongoose Schemas的定义: var ItemSchema = new mongoose.Schema({ biz: ...

  7. EF连接PostgreSql

    1.用nuget安装npgsql和EF 注意,Nuget一定要安装Npgsql的2.2.7版本,更高版本nuget在后面安装EF的时候无法自动解析. install-Package Npgsql -V ...

  8. npm不是以管理身份运行遇到的问题

    环境:win10+npm3.10.5 问题:在npm install lodash时,出现下列错误("npm-debug.log"文件内容) 0 info it worked if ...

  9. jQuery插件:jqGrid引入及基本属性

    1. jqGrid下载 jqGrid下载地址: http://www.trirand.com/blog/ jqGrid Demo: http://www.guriddo.net/demo/guridd ...

  10. OpenCASCADE Make Primitives-Box

    OpenCASCADE Make Primitives-Box eryar@163.com Abstract. By making a simple box to demonstrate the BR ...