本文以实战一个基于silverlgiht,wcf,linq to sql的网站广告轮播器,(即本站开源项目中的jacAD项目)并且是基本silverlight 2 RTM开发,操作过程与现在的silverlight3有所区别,祥细源代码请参考jacAd的实现代码)可能并没有太大实际意义,不过相信可以体验出新一代技术的特性.我并且假定你已经有一定对这些技术的基础认识.
目标:
1.简单的网站嵌入单件silverlight.(嵌入到网站)
1.1.图片轮播.视频轮播.
2.网络传输使用wcf服务,使用(basicHttpBinding)
2.1.支持使用基于流的上传与下载资源(图片,视频)
3.使用sql server 2005作为数据存储.
3.1.使用linq to sql进行数据库操作.
A.系统规划:设想中的系统框架
B.需求分析:使用用例驱动模型设计出基础需求.
广告表:
记录广告一些基础数据
ADTable
1. int id (主键)(自增1)
2. int sort (0为图片广告,1为视频广告)
3. nvarchar(MAX) title(广告标题)
4. nvarchar(MAX) img(图片服务器文件路径)
5. nvarchar(MAX) video(视频服务器文件路径).
6. nvarchar(MAX) clickurl(用户点击广告后的超连接地址)
管理者表:
记录管理者的登陆名及登陆密码
adminTable
1. int id(主键) (自增1)
2. nvarchar(50) admin_name(管理员登陆名)
3. nvarchar(50) admin_pwd(管理员密码)
参数设置表:
记录一些参数的设定值
settingTable
1. int id(主键) (自增1)
2. nvarchar(50) set_name(设定名)
3. nvarchar(50) set_value(设定值)
D.建立wcf服务项目
启动vs2008->文件->新建->项目->visual c#->web->wcf服务应用程序
名称:jacService
如图:
此时项目建立成功.如图:
项目已自动生成一个wcf服务,并有测试的接口.我们手动把这此自动生成有代码删除.
IService1.cs变成:
1: using System.Runtime.Serialization;
2: using System.ServiceModel;
3: using System.Text;
4: 5: namespace jacService
6: { 7: [ServiceContract] 8: public interface IService1
9: {
10: } 11: } Service1.svc.cs
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Runtime.Serialization;
5: using System.ServiceModel;
6: using System.Text;
7: 8: namespace jacService
9: { 10: public class Service1 : IService1
11: { 12: } 13: } E. 解决方案资源管理器右键web.config->打开方式->添加->(程序名右边的”…”按扭->C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ (如果你安装开发平台时使用了默认路径,将会在这个路径中找到)->选中SvcConfigEditor.exe ->打开->确定
如图:
此时”打开方式”对话框会新增这个工具的打开方式:
如图:
这里我介绍一下这个工具的作用.
Wcf是一种可以用配置文件设定大部份功能的技术,所以它的配置参数可以是相当复杂,如果我们在使用这个配置时使用纯手工方式编将会带来一些不必要的错误,所以windows sdk中自带了这个工具.你可以通过这个ScvConfigEditor.exe配置复杂的wcf配置文件,而且使用相当直观,可以为你的编写wcf配置文件时节省时间和免除不必要的错误.
关于这个工具的一些使用,我会在另写一编文章中深入说明.
操作继续:选中SvcConfigEditor.exe->确定
把Binding设定为basicHttpBinding.
如图:
添加一个新的”绑定”,选中左边配置中的”绑定”,点击右边的”新建绑定配置…”
如图:
选中basicHttpBinding-> 确定
如图:
设定,不设定readerQuotas将会导致无法以byte[]形式上传文件.
1: maxBufferSize="999999999" maxReceivedMessageSize="999999999" 2: 3: readerQuotas 4: 5: maxArrayLength="999999999" maxStringContentLength="999999999" 如图:
把绑定与服务关联:
如图:
点击”关闭”->保存. 到这里,web.config完成设定.
以下是完整的web.config中的wcf服务配置文件:
1: <system.serviceModel>
2: <bindings>
3: <basicHttpBinding>
4: <binding name="NewBinding0" maxBufferSize="999999999" maxReceivedMessageSize="999999999" >
5: <readerQuotas maxArrayLength="999999999" maxStringContentLength="999999999"/>
6: </binding>
7: </basicHttpBinding>
8: </bindings>
9: <services>
10: <service behaviorConfiguration="jacService.Service1Behavior"
11: name="jacService.Service1">
12: <endpoint address="" binding="basicHttpBinding" bindingConfiguration="NewBinding0"
13: contract="jacService.IService1">
14: <identity>
15: <dns value="localhost" />
16: </identity>
17: </endpoint>
18: <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
19: </service>
20: </services>
21: <behaviors>
22: <serviceBehaviors>
23: <behavior name="jacService.Service1Behavior">
24: <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点-->
25: <serviceMetadata httpGetEnabled="true"/>
26: <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
27: <serviceDebug includeExceptionDetailInFaults="false"/>
28: </behavior>
29: </serviceBehaviors>
30: </behaviors>
31: </system.serviceModel>
F. 跨域文件制作:
本于安全原因,silverlight如果要访问不同域名wcf服务必须要在wcf 服务的宿主建立一个跨域文件,否则会提示错误.
(注意:如果你的wcf服务的宿主是IIS,那么这个文件必须在IIS的根目录,而不是这个wcf服务的根目录)
操作:添加->新建项->xml文件->命名为:clientaccesspolicy.xml(这个文件名不可更改)->内容如下:
.如图:
完成.
G. 数据库连接,及linq to sql类的定义
1.连接数据库
服务器资源管理器->数据连接->添加连接
把你sql server连接上.如图:(并非所有人都一样)这里我把数据库命名为jacAdData)
2.添加linq to sql类
添加->新建项->Linq To Sql类->命名为adData.dbml
如图:
添加
3. 设计Linq to sql类
从左边的服务器资源管理器中拖放ad,admin,setting三个表到右边的空白处.
如图:
保存. 完成.
H.服务器端接口设计(为了简化复杂性,这些接口的设计没有考虑安全因数.)
1: [ServiceContract]2: public interface IService1
3: {4: #region 浏览端
5: 6: //返回指定文件,以byte[]类型
7: [OperationContract]
8: byte[] getByte(string fileName);
9: 10: #endregion
11: 12: #region 返回所有AD
13: 14: //取得所有广告
15: [OperationContract]
16: List<ad> getAD();
17: 18: #endregion
19: 20: #region 管理端
21: 22: #region 增,删,改,查
23: 24: //新增广告
25: [OperationContract]
26: bool addAD(ad data, bytedata ms);
27: 28: //查询指定id的广告
29: [OperationContract]
30: ad selectAD(int id);
31: 32: //删除广告
33: [OperationContract]
34: bool delete(int id);
35: 36: //初始化数据库
37: [OperationContract]
38: bool insdata();
39: 40: #endregion
41: 42: #region 设置
43: 44: //取得所有设定
45: [OperationContract]
46: List<setting> getsetting();
47: 48: //修改设定
49: [OperationContract]
50: bool setdata(string key, string data);
51: 52: #endregion
53: 54: #region 密码修改
55: 56: //登陆
57: [OperationContract]
58: bool login(string userid, string pwd);
59: 60: //修改密码
61: [OperationContract]
62: bool updatepwd(string oldpwd, string pwd);
63: 64: #endregion
65: 66: #endregion
67: } I.接口实现以下是Service1.svc.cs
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Runtime.Serialization;
5: using System.ServiceModel;
6: using System.Text;
7: using System.IO;
8: using System.Web.Hosting;
9: using System.ServiceModel.Activation;
10: 11: namespace jacService
12: { 13: public class Service1 : IService1
14: { 15: //实例化linq to sql类
16: adDataDataContext dc = new adDataDataContext();
17: 18: //定义图片和视频文件的路径
19: string filedir = HostingEnvironment.ApplicationPhysicalPath + @"data\";
20: 21: #region IService1 成员
22: 23: public byte[] getByte(string fileName)
24: { 25: //返回指定文件,以byte[]
26: return File.ReadAllBytes(filedir + fileName);
27: } 28: 29: public List<ad> getAD()
30: { 31: //取得所有广告
32: return dc.GetTable<ad>().ToList();
33: } 34: 35: //添加广告
36: public bool addAD(ad data, bytedata ms)
37: { 38: add(data, ms); 39: return true;
40: } 41: 42: //查询
43: public ad selectAD(int id)
44: { 45: return dc.ad.Single(d => d.id == id);
46: } 47: 48: //删除
49: public bool delete(int id)
50: { 51: //判断是否存在此广告,使用linq表达式
52: if ((from d in dc.ad where d.id == id select d).Count() > 0)
53: { 54: var data = dc.ad.Single(d => d.id == id);
55: 56: //删除文件
57: if (File.Exists(filedir + data.video))
58: { 59: File.Delete(filedir + data.video);
60: } 61: if (File.Exists(filedir + data.img))
62: { 63: File.Delete(filedir + data.img);
64: } 65: 66: //删除数据
67: dc.ad.DeleteOnSubmit(data);
68: dc.SubmitChanges(); 69: } 70: return true;
71: } 72: 73: //初始化数据库,及文件夹
74: public bool insdata()
75: { 76: try
77: {
78: var myad = dc.GetTable<ad>();
79: foreach (var mad in myad)
80: { 81: dc.ad.DeleteOnSubmit(mad); 82: } 83: dc.SubmitChanges(); 84: Directory.Delete(HostingEnvironment.ApplicationPhysicalPath + "data",true);
85: Directory.CreateDirectory(HostingEnvironment.ApplicationPhysicalPath + "data");
86: return true;
87: } 88: catch
89: {
90: return false;
91: } 92: } 93: 94: //取得所有设定
95: public List<setting> getsetting()
96: { 97: return dc.GetTable<setting>().ToList();
98: } 99: 100: //设定参数
101: public bool setdata(string key, string data)
102: { 103: //查询指定记录,使用lambda表达式
104: var ndata = dc.setting.Single(d => d.set_name == key);
105: ndata.set_value = data; 106: dc.SubmitChanges(); 107: return true;
108: } 109: 110: //管理员登陆
111: public bool login(string userid, string pwd)
112: { 113: if ((from i in dc.admin where i.admin_name==userid select i).Count() >0)
114: { 115: admin data = dc.admin.Single(d => d.admin_name == userid); 116: 117: if (data.admin_pwd == pwd)
118: { 119: return true;
120: } 121: else
122: {
123: return false;
124: } 125: } 126: else
127: {
128: return false;
129: } 130: 131: } 132: 133: //管理员修改密码
134: public bool updatepwd(string oldpwd, string pwd)
135: { 136: var user = dc.admin.Single(d => d.admin_name == "admin");
137: if (oldpwd.Equals(user.admin_pwd))
138: { 139: user.admin_pwd = pwd; 140: dc.SubmitChanges(); 141: return true;
142: } 143: else
144: {
145: return false;
146: } 147: } 148: 149: #endregion
150: 151: //新增操作
152: void add(ad data, bytedata ms)
153: { 154: if (data.sort == 0)
155: { 156: StreamToFile(ms.filedata, filedir + data.img); 157: dc.ad.InsertOnSubmit(data); 158: dc.SubmitChanges(); 159: } 160: else if (data.sort == 1)
161: { 162: StreamToFile(ms.filedata, filedir + data.video); 163: dc.ad.InsertOnSubmit(data); 164: dc.SubmitChanges(); 165: } 166: } 167: 168: //将流写为文件
169: void StreamToFile(byte[] bytes, string fileName)
170: { 171: FileStream fs = new FileStream(fileName, FileMode.Create);
172: BinaryWriter bw = new BinaryWriter(fs);
173: bw.Write(bytes); 174: bw.Close(); 175: fs.Close(); 176: } 177: } 178: 179: //数据契约
180: [DataContract]
181: public class bytedata
182: {
183: [DataMember] 184: public byte[] filedata { get; set; }
185: } 186: 187: } 188: J.1.打开adData.designer.cs文件:如图:
数据契约说明:在wcf开发中,当我们需要传输一些我们自定义的数据类型时,这些数据类型都必须为可序列化和返序列化,wcf为我们提供了十方便的使用方式,只要在数据定义时加上DataContract"数据契约"即可,这样自定义数据在传输过程中会自动序列化和反序列化,而DataMember即为数据契约的成员,如果数据契约成员没有被标识为DataMember,那么wcf会视此成员为不进行序列化和反序列化.以下是一个简单的例子:
1: //数据契约
2: [DataContract]3: public class mydata
4: {5: //数据成员
6: [DataMember]
7: public string userid { get; set; }
8: //数据成员
9: [DataMember]
10: public int age { get; set; }
11: //非数据成员
12: public string address { get; set; }
13: } 2.添加System.Runtime引用.
以下是整个adData.designer.cs文件修改后的内容,(注意using System.Runtime.Serialization;和
[DataContract],[DataMember]和定义.)
1: namespace jacService
2: {3: using System.Data.Linq;
4: using System.Data.Linq.Mapping;
5: using System.Data;
6: using System.Collections.Generic;
7: using System.Reflection;
8: using System.Linq;
9: using System.Linq.Expressions;
10: using System.ComponentModel;
11: using System;
12: using System.Runtime.Serialization;
13: [System.Data.Linq.Mapping.DatabaseAttribute(Name = "jacADdata")]
14: public partial class adDataDataContext : System.Data.Linq.DataContext
15: {16: private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
17: #region Extensibility Method Definitions
18: partial void OnCreated();
19: partial void Insertad(ad instance);
20: partial void Updatead(ad instance);
21: partial void Deletead(ad instance);
22: partial void Insertadmin(admin instance);
23: partial void Updateadmin(admin instance);
24: partial void Deleteadmin(admin instance);
25: partial void Insertsetting(setting instance);
26: partial void Updatesetting(setting instance);
27: partial void Deletesetting(setting instance);
28: #endregion
29: public adDataDataContext() :
30: base(global::System.Configuration.ConfigurationManager.ConnectionStrings["jacADdataConnectionString"].ConnectionString, mappingSource)
31: { 32: OnCreated(); 33: }34: public adDataDataContext(string connection) :
35: base(connection, mappingSource)
36: { 37: OnCreated(); 38: }39: public adDataDataContext(System.Data.IDbConnection connection) :
40: base(connection, mappingSource)
41: { 42: OnCreated(); 43: }44: public adDataDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
45: base(connection, mappingSource)
46: { 47: OnCreated(); 48: }49: public adDataDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
50: base(connection, mappingSource)
51: { 52: OnCreated(); 53: }54: public System.Data.Linq.Table<ad> ad
55: {56: get
57: {
58: return this.GetTable<ad>();
59: } 60: }61: public System.Data.Linq.Table<admin> admin
62: {63: get
64: {
65: return this.GetTable<admin>();
66: } 67: }68: public System.Data.Linq.Table<setting> setting
69: {70: get
71: {
72: return this.GetTable<setting>();
73: } 74: } 75: } 76: [DataContract]77: [Table(Name = "dbo.ad")]
78: public partial class ad : INotifyPropertyChanging, INotifyPropertyChanged
79: {
80: private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
81: private int _id;
82: private int _sort;
83: private string _title;
84: private string _img;
85: private string _video;
86: private string _clickurl;
87: #region Extensibility Method Definitions
88: partial void OnLoaded();
89: partial void OnValidate(System.Data.Linq.ChangeAction action);
90: partial void OnCreated();
91: partial void OnidChanging(int value);
92: partial void OnidChanged();
93: partial void OnsortChanging(int value);
94: partial void OnsortChanged();
95: partial void OntitleChanging(string value);
96: partial void OntitleChanged();
97: partial void OnimgChanging(string value);
98: partial void OnimgChanged();
99: partial void OnvideoChanging(string value);
100: partial void OnvideoChanged();
101: partial void OnclickurlChanging(string value);
102: partial void OnclickurlChanged();
103: #endregion
104: public ad()
105: {106: OnCreated();107: }108: [DataMember(Order = 1)]109: [Column(Storage = "_id", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
110: public int id
111: {112: get
113: {
114: return this._id;
115: }116: set
117: {
118: if ((this._id != value))
119: {120: this.OnidChanging(value);
121: this.SendPropertyChanging();
122: this._id = value;
123: this.SendPropertyChanged("id");
124: this.OnidChanged();
125: }126: }127: }128: [DataMember(Order = 2)]129: [Column(Storage = "_sort", DbType = "Int NOT NULL")]
130: public int sort
131: {132: get
133: {
134: return this._sort;
135: }136: set
137: {
138: if ((this._sort != value))
139: {140: this.OnsortChanging(value);
141: this.SendPropertyChanging();
142: this._sort = value;
143: this.SendPropertyChanged("sort");
144: this.OnsortChanged();
145: }146: }147: }148: [DataMember(Order = 3)]149: [Column(Storage = "_title", DbType = "NVarChar(MAX) NOT NULL", CanBeNull = false)]
150: public string title
151: {152: get
153: {
154: return this._title;
155: }156: set
157: {
158: if ((this._title != value))
159: {160: this.OntitleChanging(value);
161: this.SendPropertyChanging();
162: this._title = value;
163: this.SendPropertyChanged("title");
164: this.OntitleChanged();
165: }166: }167: }168: [DataMember(Order = 4)]169: [Column(Storage = "_img", DbType = "NVarChar(MAX)")]
170: public string img
171: {172: get
173: {
174: return this._img;
175: }176: set
177: {
178: if ((this._img != value))
179: {180: this.OnimgChanging(value);
181: this.SendPropertyChanging();
182: this._img = value;
183: this.SendPropertyChanged("img");
184: this.OnimgChanged();
185: }186: }187: }188: [DataMember(Order = 5)]189: [Column(Storage = "_video", DbType = "NVarChar(MAX)")]
190: public string video
191: {192: get
193: {
194: return this._video;
195: }196: set
197: {
198: if ((this._video != value))
199: {200: this.OnvideoChanging(value);
201: this.SendPropertyChanging();
202: this._video = value;
203: this.SendPropertyChanged("video");
204: this.OnvideoChanged();
205: }206: }207: }208: [DataMember(Order = 6)]209: [Column(Storage = "_clickurl", DbType = "NVarChar(MAX) NOT NULL", CanBeNull = false)]
210: public string clickurl
211: {212: get
213: {
214: return this._clickurl;
215: }216: set
217: {
218: if ((this._clickurl != value))
219: {220: this.OnclickurlChanging(value);
221: this.SendPropertyChanging();
222: this._clickurl = value;
223: this.SendPropertyChanged("clickurl");
224: this.OnclickurlChanged();
225: }226: }227: }228: public event PropertyChangingEventHandler PropertyChanging;
229: public event PropertyChangedEventHandler PropertyChanged;
230: protected virtual void SendPropertyChanging()
231: {232: if ((this.PropertyChanging != null))
233: {234: this.PropertyChanging(this, emptyChangingEventArgs);
235: }236: }237: protected virtual void SendPropertyChanged(String propertyName)
238: {239: if ((this.PropertyChanged != null))
240: {241: this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
242: }243: }244: }245: [DataContract]246: [Table(Name = "dbo.admin")]
247: public partial class admin : INotifyPropertyChanging, INotifyPropertyChanged
248: {
249: private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
250: private int _id;
251: private string _admin_name;
252: private string _admin_pwd;
253: #region Extensibility Method Definitions
254: partial void OnLoaded();
255: partial void OnValidate(System.Data.Linq.ChangeAction action);
256: partial void OnCreated();
257: partial void OnidChanging(int value);
258: partial void OnidChanged();
259: partial void Onadmin_nameChanging(string value);
260: partial void Onadmin_nameChanged();
261: partial void Onadmin_pwdChanging(string value);
262: partial void Onadmin_pwdChanged();
263: #endregion
264: public admin()
265: {266: OnCreated();267: }268: [DataMember(Order = 1)]269: [Column(Storage = "_id", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
270: public int id
271: {272: get
273: {
274: return this._id;
275: }276: set
277: {
278: if ((this._id != value))
279: {280: this.OnidChanging(value);
281: this.SendPropertyChanging();
282: this._id = value;
283: this.SendPropertyChanged("id");
284: this.OnidChanged();
285: }286: }287: }288: [DataMember(Order = 2)]289: [Column(Storage = "_admin_name", DbType = "NVarChar(50)")]
290: public string admin_name
291: {292: get
293: {
294: return this._admin_name;
295: }296: set
297: {
298: if ((this._admin_name != value))
299: {300: this.Onadmin_nameChanging(value);
301: this.SendPropertyChanging();
302: this._admin_name = value;
303: this.SendPropertyChanged("admin_name");
304: this.Onadmin_nameChanged();
305: }306: }307: }308: [DataMember(Order = 3)]309: [Column(Storage = "_admin_pwd", DbType = "NVarChar(50)")]
310: public string admin_pwd
311: {312: get
313: {
314: return this._admin_pwd;
315: }316: set
317: {
318: if ((this._admin_pwd != value))
319: {320: this.Onadmin_pwdChanging(value);
321: this.SendPropertyChanging();
322: this._admin_pwd = value;
323: this.SendPropertyChanged("admin_pwd");
324: this.Onadmin_pwdChanged();
325: }326: }327: }328: public event PropertyChangingEventHandler PropertyChanging;
329: public event PropertyChangedEventHandler PropertyChanged;
330: protected virtual void SendPropertyChanging()
331: {332: if ((this.PropertyChanging != null))
333: {334: this.PropertyChanging(this, emptyChangingEventArgs);
335: }336: }337: protected virtual void SendPropertyChanged(String propertyName)
338: {339: if ((this.PropertyChanged != null))
340: {341: this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
342: }343: }344: }345: [DataContract]346: [Table(Name = "dbo.setting")]
347: public partial class setting : INotifyPropertyChanging, INotifyPropertyChanged
348: {
349: private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
350: private int _id;
351: private string _set_name;
352: private string _set_value;
353: #region Extensibility Method Definitions
354: partial void OnLoaded();
355: partial void OnValidate(System.Data.Linq.ChangeAction action);
356: partial void OnCreated();
357: partial void OnidChanging(int value);
358: partial void OnidChanged();
359: partial void Onset_nameChanging(string value);
360: partial void Onset_nameChanged();
361: partial void Onset_valueChanging(string value);
362: partial void Onset_valueChanged();
363: #endregion
364: public setting()
365: {366: OnCreated();367: }368: [DataMember(Order = 1)]369: [Column(Storage = "_id", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
370: public int id
371: {372: get
373: {
374: return this._id;
375: }376: set
377: {
378: if ((this._id != value))
379: {380: this.OnidChanging(value);
381: this.SendPropertyChanging();
382: this._id = value;
383: this.SendPropertyChanged("id");
384: this.OnidChanged();
385: }386: }387: }388: [DataMember(Order = 2)]389: [Column(Storage = "_set_name", DbType = "NVarChar(50)")]
390: public string set_name
391: {392: get
393: {
394: return this._set_name;
395: }396: set
397: {
398: if ((this._set_name != value))
399: {400: this.Onset_nameChanging(value);
401: this.SendPropertyChanging();
402: this._set_name = value;
403: this.SendPropertyChanged("set_name");
404: this.Onset_nameChanged();
405: }406: }407: }408: [DataMember(Order = 3)]409: [Column(Storage = "_set_value", DbType = "NVarChar(50)")]
410: public string set_value
411: {412: get
413: {
414: return this._set_value;
415: }416: set
417: {
418: if ((this._set_value != value))
419: {420: this.Onset_valueChanging(value);
421: this.SendPropertyChanging();
422: this._set_value = value;
423: this.SendPropertyChanged("set_value");
424: this.Onset_valueChanged();
425: }426: }427: }428: public event PropertyChangingEventHandler PropertyChanging;
429: public event PropertyChangedEventHandler PropertyChanged;
430: protected virtual void SendPropertyChanging()
431: {432: if ((this.PropertyChanging != null))
433: {434: this.PropertyChanging(this, emptyChangingEventArgs);
435: }436: }437: protected virtual void SendPropertyChanged(String propertyName)
438: {439: if ((this.PropertyChanged != null))
440: {441: this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
442: }443: }444: }445: } 到此. 服务器端已经设计完成.
运行后如图:
下一步客户端开发.
首先,我先行介绍一下一个有有到的工具软件.Expression Blend.此工具是专为wpf而开发UI设计工具,
可以很直观并快速的开发出理想的软件UI,也是程式员与UI工程师的分散协同工作工作,程序员可以用vs2008编写代码,UI工程师可以使用Blend开发UI,(Expression studio还有其他的一些工具,包括,design,encoder,media等,这里不祥说)
要想可以开发silverlight我们必须安装silverlight的开发扩展,目前是rc1,运行时是RTW.
安装地址(http://silverlight.net/GetStarted/)
现在我假定你的开发平台已经安装好所有开发工具(vs2008+silverlight Rc1扩展,silverlight RTW runtim,Expression blend)
K.建立AD客户端(silverlight)
1.解决方案->添加->新建项目->visual c#->silverlight->silverlight应用程序
名称:Persenter->确定->在生成时自动生成测试页以承载silverlgiht(G)
如图:
2.再用相同的方法添加管理者的silverlight客户端名称为(admin).此时项目资管理器中会多两个silvelight项目.如图:
L.引用wcf服务.(这里介绍如何在silverlight中引用wcf服务)
1.扩开Persenter项目:
右键引用->添加服务引用->地址->http://localhost:3725/Service1.svc(此为wcf服务地址,取得方法就是通过运行服务项目得到,如上服务设计完成图中的IE的url地址.)->确定->命名空间我不作修改使用ServiceReference1.此时项目会自动生成客户端的代理文件.
2.设计广告轮播器.
Persenter->右键page.xaml->在Expression Blend中打开->进入到blend中.
设计成如下:
1: <UserControl x:Class="Persenter.Page"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="Auto" Height="Auto">
4: <Grid x:Name="LayoutRoot" Background="#FFD0F284" Opacity="1">
5: <Image Margin="0,0.5,0,37" x:Name="img1" Stretch="UniformToFill"/>
6: <TextBlock Height="25" Margin="26,0,26,8" VerticalAlignment="Bottom" TextWrapping="Wrap" x:Name="tbk_title" Text="Title" TextAlignment="Center" Foreground="#FF4F4F39" HorizontalAlignment="Stretch" Cursor="Hand" Width="350" FontSize="14"/>
7: <TextBlock Height="25" HorizontalAlignment="Left" Margin="8,0,0,8" VerticalAlignment="Bottom" Width="14" Text="<" TextWrapping="Wrap" Foreground="#FFEC2B2B" x:Name="left"/>
8: <TextBlock Height="25" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="14" Text=">" TextWrapping="Wrap" x:Name="right" Foreground="#FFEC2B2B"/>
9: <MediaElement x:Name="video" Opacity="1" Volume="1" Margin="0,0,0,37"/>
10: 11: </Grid>
12: </UserControl>
3.设计app.xaml.cs文件,让silverlight可以接受外来参数的传入.
1: namespace Persenter
2: { 3: public partial class App : Application
4: {
5: public IDictionary<string, string> inputdata;
6: 7: private void Application_Startup(object sender, StartupEventArgs e)
8: { 9: this.RootVisual = new Page();
10: inputdata = e.InitParams; 11: } 这样我们可以通过设定silverlgiht所在的asp.net页中的控件定义参数为行数据传入.
例子:
1: <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/Persenter.xap"
2: MinimumVersion="2.0.30523" Width="100%" Height="100%"
3: InitParameters="参数1名=参数1值,参数2名=参数2值"/>
使用时:
1: App myapp = App.Current as App;
2: var url = myapp.inputdata.Single(d => d.Key.Equals("参数1名"));
3: var Ivalue = url.Value; 4.添加一个新类以管理取得从外边传入的wcf服务地址.类名为(serverManager.cs)
这里实例了一个wcf服务的客户端代理.命名为sc.
而且定义了一个方法返回一个使用了传入服务地址的代理命名为getpox()
1: namespace Persenter
2: {3: internal class serverManager
4: {
5: private static ServiceReference1.Service1Client sc = new Persenter.ServiceReference1.Service1Client();
6: 7: internal static ServiceReference1.Service1Client getPox()
8: {9: if (sc.State == System.ServiceModel.CommunicationState.Created)
10: {11: App myapp = App.Current as App;
12: var url = myapp.inputdata.Single(d => d.Key.Equals("server"));
13: sc.Endpoint.Address = new System.ServiceModel.EndpointAddress(url.Value);
14: return sc;
15: }16: else
17: {
18: return sc;
19: }20: }21: }22: } 23: 5.page.xaml.cs代码(这里是实现广告的核心)
1: namespace Persenter
2: {3: public partial class Page : UserControl
4: {5: //自定义的timer,这里我使用了Storyboard,利用Storyboard的conpleted事件不断重复.
6: Storyboard looper;
7: 8: public Page()
9: { 10: InitializeComponent();11: //实例化自定义timer
12: looper = new Storyboard();
13: //设定重复时间,这里默认值设为5秒
14: looper.Duration = new Duration(TimeSpan.FromSeconds(5));
15: //注册completed事件
16: looper.Completed += new EventHandler(looper_Completed);
17: //注册初始化事件
18: this.Loaded += new RoutedEventHandler(Page_Loaded);
19: //注册上翻事件
20: this.left.MouseLeftButtonDown += left_MouseLeftButtonDown;
21: //注册下翻事件
22: this.right.MouseLeftButtonDown += right_MouseLeftButtonDown;
23: } 24: 25: //下翻时件
26: void right_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
27: {28: if (sumer < counter)
29: { 30: sumer += 1; 31: } 32: showad(ads[sumer]); 33: looper.Stop(); 34: looper.Begin(); 35: } 36: 37: //上翻事件
38: void left_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
39: {40: if (sumer > 0)
41: { 42: sumer -= 1; 43: } 44: showad(ads[sumer]); 45: looper.Stop(); 46: looper.Begin(); 47: } 48: 49: //timer重复事件
50: void looper_Completed(object sender, EventArgs e)
51: {52: if (sumer < counter)
53: { 54: sumer += 1; 55: showad(ads[sumer]); 56: }57: else if (sumer == counter)
58: { 59: sumer = -1; 60: } 61: looper.Begin(); 62: } 63: 64: //运算子
65: int sumer = 0;
66: int counter = 0;
67: 68: //显示广告方法
69: void beginadshow(List<ad> data)
70: { 71: counter = data.Count() - 1; 72: showad(data[sumer]); 73: looper.Begin(); 74: } 75: 76: //wcf服务的客户端代理
77: Service1Client sc;
78: 79: void Page_Loaded(object sender, RoutedEventArgs e)
80: {81: //加载服务
82: sc = serverManager.getPox();
83: //注册控件的鼠标事件
84: tbk_title.MouseLeftButtonDown += tbk_title_MouseLeftButtonDown;
85: img1.MouseLeftButtonDown += tbk_title_MouseLeftButtonDown; 86: video.MouseLeftButtonDown += tbk_title_MouseLeftButtonDown; 87: 88: //注册服务异步完成事件
89: sc.getByteCompleted += sc_getByteCompleted;
90: sc.getsettingCompleted += sc_getsettingCompleted; 91: sc.getADCompleted += sc_getADCompleted; 92: 93: //异步调用wcf服务的getsetting和getad方法
94: sc.getsettingAsync();
95: sc.getADAsync(); 96: } 97: 98: //getsetting完成后的操作
99: void sc_getsettingCompleted(object sender, getsettingCompletedEventArgs e)
100: {101: //取得返回结果(服务器端必须把setting定义为 [DataContract]才能在这里还原数据.
102: List<setting> set = new List<setting>(e.Result);
103: //取得setting后把属性设定
104: this.Width = double.Parse(set.Single(d => d.set_name == "宽度").set_value);
105: this.Height = double.Parse(set.Single(d => d.set_name == "高度").set_value);
106: this.tbk_title.FontSize = double.Parse(set.Single(d => d.set_name == "字体大小").set_value);
107: this.video.Volume = double.Parse(set.Single(d => d.set_name == "视频音量").set_value);
108: clickmode = int.Parse(set.Single(d => d.set_name == "连接方式").set_value);
109: }110: 111: //getad完成后的操作
112: void sc_getADCompleted(object sender, getADCompletedEventArgs e)
113: {114: //取得广告集合
115: ads = new List<ad>(e.Result);
116: beginadshow(ads);117: }118: 119: //用户点击后的超连接
120: Uri clickurl;
121: //广告集合定义
122: List<ad> ads;
123: //用户点击后的超连接方式,1:在当前页打开,0:从新页个打开.
124: int clickmode = 1;
125: 126: //广告显示
127: void showad(ad d)
128: {129: //image的souce属性初始化
130: img1.ClearValue(Image.SourceProperty);
131: //title显不
132: tbk_title.Text = d.title;
133: //取得超连接
134: clickurl = new Uri(d.clickurl);
135: //图片或视频的运算子,0:图片,1:视频
136: adsort = d.sort;
137: //判断并设定图片或视频到控件.
138: if (d.sort == 0)
139: {140: video.Opacity = 0;141: video.Stop();142: //向服务器申请图片内容byte[]
143: sc.getByteAsync(d.img);
144: }145: else if (d.sort == 1)
146: {147: video.Opacity = 1;148: //向服务器申请视频内容byte[]
149: sc.getByteAsync(d.video);
150: }151: }152: 153: //定义图片或视频的运算子,0:图片,1:视频
154: int adsort = 0;
155: 156: //向服务器申请视频内容byte[]完成
157: void sc_getByteCompleted(object sender, getByteCompletedEventArgs e)
158: {159: //还原byte[]到图片或视频播控件
160: BitmapImage bi = new BitmapImage();
161: MemoryStream data = new MemoryStream(e.Result);
162: 163: if (adsort == 0)
164: {165: bi.SetSource(data);166: img1.Source = bi;167: }168: else if (adsort == 1)
169: {170: video.SetSource(data);171: video.Play();172: }173: }174: 175: //鼠标点击事件
176: void tbk_title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
177: {178: if (clickmode == 1)
179: {180: //以新页方式打开超连接
181: HtmlPage.Window.Navigate(clickurl, "blend");
182: }183: else
184: {
185: //以本页方式打开
186: HtmlPage.Window.Navigate(clickurl);
187: }188: 189: }190: }191: 192: }到此广告轮播展示器完成.
欢迎您参与更多关于此话题的讨论,本文原创地址为:http://funsl.com admin博客
评论
我是新手,按照说明配置一切顺利,但在运行时 d => d.Key.Equals("server") 这个地方报错。
serverManager.cc 文件 第24行 报错。
感觉是 d 没有定义
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
namespace Persenter
{
internal class serverManager
{
private static ServiceReference1.Service1Client sc = new Persenter.ServiceReference1.Service1Client();
internal static ServiceReference1.Service1Client getPox()
{
if (sc.State== System.ServiceModel.CommunicationState.Created)
{
App myapp = App.Current as App;
var url = myapp.inputdata.Single(d => d.Key.Equals("server")); //此处报错
sc.Endpoint.Address = new System.ServiceModel.EndpointAddress(url.Value);
return sc;
}
else
{
return sc;
}
}
}
}
Single是个委托,貌似楼主没有给出托管代码么。
是的sl3之后就可以通过用html去定义initparams。这样就可以在sl2之后的版本中使用,你可以查查相关initparams在sliverlight 3中的用法!
永远支持内裤超人!
理想创造美好未来!