在Mainpage后台页面使用Com时需要引入命名空间:
1: using System.Runtime.InteropServices.Automation;
2: using System.Collections;
3: using System.Threading;
页面加载初始化DataGrid中填充相关的数据:
1: /// <summary>
2: /// 加载数据
3: /// </summary>
4: void MainPage_Loaded(object sender, RoutedEventArgs e)
5:
{
6: var list = new List<PersonEntity>();
7: var rand = new Random();
8: for (int i = 0; i < 9; i++)
9: list.Add(new PersonEntity
10:
{
11: Name = "Person:" + i,
12:
Age = rand.Next(20),
13: Gender = (i % 2 == 0 ? "Male" : "Female" ),
14:
});
15:
16: //Bind
17:
dataGrid1.ItemsSource = list;
18:
}
利用C# 新特性实现DataGrid数据导出到NotePad[记事本中]:
1: /// <summary>
2: /// 核心操作 导出数据到记事本.
3: /// Sign by chenki Date:2010年11月8日21:51:18
4: /// </summary>
5: private void TextExport_Click(object sender, RoutedEventArgs e)
6:
{
7: // Check if using AutomationFactory is allowed.
8: if (!AutomationFactory.IsAvailable)
9:
{
10: MessageBox.Show("This function need the silverlight application running at evaluated OOB mode." );
11:
}
12: else
13:
{
14: // Use shell to open notepad application.
15: using (dynamic shell = AutomationFactory.CreateObject("WScript.Shell" ))
16:
{
17: shell.Run(@"%windir%/notepad" , 5);
18:
Thread.Sleep(100);
20: shell.SendKeys("Name{Tab}Age{Tab}Gender{Enter}" );
21: foreach (PersonEntity item in dataGrid1.ItemsSource as IEnumerable)
22: shell.SendKeys(item.Name + "{Tab}" + item.Age + "{Tab}" + item.Gender + "{Enter}" );
23:
}
24:
}
25:
}
注意所有的导出操作全部OOB模式下执行才能有权限实现,这个稍微我会详细解释:
当运行起程序后安装本地桌面:
在OOB模式下运行起来:
导出到记事本效果:
实现World就相对麻烦很多.在World导出对应OFFices套件必须是07 版本或是更高版本. 如下实现:
1: /// <summary>
2: /// 核心操作 数据导出到World中
3: /// sign by chenkai DAte:2010年11月8日22:06:15
4: /// </summary>
5: private void WordExport_Click(object sender, RoutedEventArgs e)
6:
{
7: // Check if using AutomationFactory is allowed.
8: if (!AutomationFactory.IsAvailable)
9:
{
10: MessageBox.Show("This function need the silverlight application running at evaluated OOB mode." );
11:
}
12: else
13:
{
14: // Create Word automation object.
15: dynamic word = AutomationFactory.CreateObject("Word.Application" );
16: word.Visible = true ;
17:
18: // Create a new word document.
19:
dynamic doc = word.Documents.Add();
20:
21: // Write title
22:
dynamic range1 = doc.Paragraphs[1].Range;
23: range1.Text = "Silverlight4 Word Automation Sample/n" ;
24:
range1.Font.Size = 24;
25: range1.Font.Bold = true ;
26:
27: var list = dataGrid1.ItemsSource as List<PersonEntity>;
28:
29:
dynamic range2 = doc.Paragraphs[2].Range;
30:
range2.Font.Size = 12;
31: range2.Font.Bold = false ;
32:
33: // Create table
34: doc.Tables.Add(range2, list.Count+1, 3, null , null );
35:
36:
dynamic cell = doc.Tables[1].Cell(1, 1);
37: cell.Range.Text = "Name" ;
38: cell.Range.Font.Bold = true ;
39:
40:
cell = doc.Tables[1].Cell(1, 2);
41: cell.Range.Text = "Age" ;
42: cell.Range.Font.Bold = true ;
43:
44:
cell = doc.Tables[1].Cell(1, 3);
45: cell.Range.Text = "Gender" ;
46: cell.Range.Font.Bold = true ;
47:
48: // Fill data to table cells
49: for (int i = 0; i < list.Count; i++)
50:
{
51:
cell = doc.Tables[1].Cell(i + 2, 1);
52:
cell.Range.Text = list[i].Name;
53:
54:
cell = doc.Tables[1].Cell(i + 2, 2);
55:
cell.Range.Text = list[i].Age;
56:
57:
cell = doc.Tables[1].Cell(i + 2, 3);
58:
cell.Range.Text = list[i].Gender;
59:
}
60:
61: if (_isprint)
62:
{
63: // Print the word directly without preview.
64:
doc.PrintOut();
65:
}
66:
67:
}
68:
}
Word 07版导出效果:
有些人为何要为对于数据导出 类似文件操作等为何要在OOB模式运行. 这一切都源自Silverlight的为了运行环境和部署的安全上做的沙箱设计.COM组件是客户端运行的,OOB模式获得高级权限跳出沙箱设计对本地系 统文件操作权限的限制. 如果在安全沙盒模型下的,那就无法调用COM组件. 关于Silverlight的沙箱设计相比做过WP7嵌入式数据库本地访问应该是对这点深有体会. 虽然完整保证Silverlight安全但却本地系统交互上做了诸多限制对开发产生诸多不便.
<2> 关于dynamic关键字
在Visual C# 2010中引入了一种新的dynamic类型,该类型是一个静态的(static)类型,但是一个dynamic类型的对象会绕过静态类型检查。在大多数 情况下dynamic和object类型有些相似,但是在编译时,dynamic类型被假定为支持任何操作,也就是说dynamic类型的对象可以是一个 Office对象,可以是一个COM对象或者是DOM对象,而如果在运行时发现该对象不是期望的对象则会抛出一个运行时异常.
从上面代码可以看出大量使用了Dynamic类型. 注意我们开始编码引入空间System.Runtime.InteropServices.Automation 下 AutomationFactory 类提供对已注册的自动化服务器的访问.
自动化是应用程序用于向脚本撰写工具和其他应用程序公开功能的一种基于 Windows 的技术。例如,可以使用自动化将 Office 功能添加到基于 Silverlight 的应用程序中 如上操作就是.
应用程序或公开功能的组件称作自动化服务器,而访问功能的应用程序称作自动化客户端。因为必须预先安装并在完全信任下运行自动化服务器,所以 Silverlight 仅将受信任的应用程序作为自动化客户端, 这也是为什么要在OOB模式下一个重要原因.
如上对NotePad导出操作:
1: using (dynamic shell = AutomationFactory.CreateObject("WScript.Shell" ))
2:
{
3: shell.Run(@"%windir%/notepad" , 5);
4:
Thread.Sleep(100);
5:
6: shell.SendKeys("Name{Tab}Age{Tab}Gender{Enter}" );
7: foreach (PersonEntity item in dataGrid1.ItemsSource as IEnumerable)
8: shell.SendKeys(item.Name + "{Tab}" + item.Age + "{Tab}" + item.Gender + "{Enter}" );
9:
}
利用Dynamic对象封装Shell脚本来执行数据导出. 而作为OFFice套件之一的World则完全不同.采用直接动态创建一个对象方式CreateObject 或 GetObject 方法检索对自动化服务器的后期绑定引用,若要将引用用作后期绑定对象,必须将其分配给 Object 类型(在 Visual Basic 中)或dynamic 类型(在 C# 中)的变量. 同理对于outLook操作也是同样道理
Silverlight 只能使用已安装的自动化服务器;因此,当它们找不到要求的进程 ID 时,CreateObject 和 GetObject 方法将引发异常。
下表显示了几个常见的 progID 值:
-
办公自动化:Outlook.Application、Excel.Application、PowerPoint.Application
-
系统自动化:Scripting.FileSystemObject、WScript.Shell、Shell.Application
-
Windows 管理规范:WbemScripting.SWbemLocator
一般情况下,这些字符串映射到自动化服务器的特定版本。如果服务器有多个版本,则该服务器通常会添加版本编号到该进程 ID
类似操作OutLook就极为简单:
1: private dynamic outlook;
2:
3: private bool InitializeOutlook()
4:
{
5: try
6:
{
7: // If GetObject throws an exception, then Outlook is
8: // either not running or is not available.
9: outlook = AutomationFactory.GetObject("Outlook.Application" );
10: return true ;
11:
}
12: catch (Exception)
13:
{
14: try
15:
{
16: // Start Outlook and display the Inbox, but minimize
17: // it to avoid hiding the Silverlight application.
18:
outlook =
19: AutomationFactory.CreateObject("Outlook.Application" );
20: outlook.Session.GetDefaultFolder(6 /* Inbox */ ).Display();
21: outlook.ActiveWindow.WindowState = 1; // minimized
22: return true ;
23:
}
24: catch (Exception)
25:
{
26: // Outlook is unavailable.
27: return false ;
28:
}
29:
}
30:
}
如上关于Silverlight 4使用Com组件最为简短的分析. 使用范围主要涉及到我们常用的OFFice套件中.