在本篇開始前,首先感謝每一位留下反饋評論的朋友,在我看來,博客不僅僅是簡單的分享,同時也是一個學習和發現的過程。在閱讀完一篇文章能對其有所評論和提問,也是一種思考的表現。
在上篇“[Silverlight實例教程 - Out of Browser與COM的交互基礎](http://www.cnblogs.com/jv9/archive/2010/07/23/1783379.html)”中,我們討論了Silverlight的OOB應用訪問COM組件基礎知識,在大家的反饋中,有不少朋友提出疑問,Silverlight對于COM的支持,使其失去跨平臺的優越性,另外,Silverlight僅有Out of Browser模式能支持COM,是否仍舊存在較大的局限性? 對此在本篇我們不進行長篇分析和討論,只是簡單的把我的看法說一下。
Silverlight Out of Browser從Silverlight 3 到現在Silverlight 4,一直遵循跨平臺的原則,在微軟官方有相關的解釋,
Linux,Moonlight從第一個版本發布,就已經有了高級權限模型,在GtkWidget中Moonlight具有full-trust的能力。 也就是說,Silverlight具有信任權限提升,而Mono具有full-trust模式。
Mac, 由于Mac沒有Com的概念,所以,Silverlight的COM無法在Mac中運行,但是微軟官方也正在尋找一種方式,嘗試使用一種模擬的方式來實現在Mac上運行COM的效果,例如,運行AppleScript

在上面的腳本中可以看出,Mac如何通過AppleScript來調用Office Word的,而這樣的方式其實也就是Mac對COM的調用,在以后Silverlight的版本中,如果加入對AppleScripts的支持即可在Mac上支持COM的運行;
從上面的描述來看,Silverlight的OOB應用跨平臺,并非不能解決,只是時間的問題。作為技術人員,經常對一門技術的前景進行展望,而需要注意的是,盡量不要使用其短處與其他技術的長處進行相比較,這樣的對比結果,只會干擾自己的視線和思路。一門能掙錢的技術,就已經算是一門好技術了。
**Out of Browser與Office的互操作**
言歸正傳,本篇將繼續介紹Silverlight的Out of Browser應用與Office COM組件的交互。相信大家對微軟的Office系列并不陌生了,Office在企業項目中使用頻率較高,例如在日常項目中經常與遇到導出列表到Excel,或者發送郵件等功能需求,所以微軟將其許多功能封裝成COM組件,供開發人員使用,增強其應用的靈活性。本篇,我將演示在Silverlight的OOB應用中,如何使用Office Outlook,Word,Excel組件。
我們仍舊使用上篇的項目代碼,對其進行擴展,大家可以到上篇下載演示項目代碼。
?
在開始功能代碼前,首先需要在UI界面ToolBar中添加三個Button來響應其事件。

~~~
??<Border?BorderBrush="{StaticResource?GlossyBlack_StrokeGradient}"?BorderThickness="1"?CornerRadius="2"?Margin="1"?Padding="0,1,1,1">
????????<StackPanel>
??????????????<StackPanel?Orientation="Horizontal">
???????????????????<Button?IsTabStop="False"?Width="56"?Height="80"?Style="{StaticResource?BlackGlossyButton}"?Margin="1,0,0,0"?Foreground="White"??x:Name="sendemailBtn"?Click="sendemailBtn_Click">
?????????????????????????<StackPanel>
???????????????????????????????<Image?VerticalAlignment="Top"?HorizontalAlignment="Center"?Source="/SilverlightOOBDemo;component/Images/SendEmail.png"?Margin="0,-5,0,0"?Stretch="None"?/>
???????????????????????????????<TextBlock?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,3,0,0"?Text="發郵件"?TextWrapping="Wrap"/>
??????????????????????????</StackPanel>
????????????????????</Button>
???????????????????<Button?IsTabStop="False"?Width="56"?Height="80"?Style="{StaticResource?BlackGlossyButton}"?Margin="1,0,0,0"?Foreground="White"??x:Name="excelBtn"?Click="excelBtn_Click">
?????????????????????????<StackPanel>
?????????????????????????????<Image?VerticalAlignment="Top"?HorizontalAlignment="Center"?Source="/SilverlightOOBDemo;component/Images/Excel.png"?Margin="0,-5,0,0"?Stretch="None"?/>
?????????????????????????????<TextBlock?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,3,0,0"?Text="Excel"?TextWrapping="Wrap"/>
?????????????????????????</StackPanel>
???????????????????</Button>
???????????????????<Button?IsTabStop="False"?Width="56"?Height="80"?Style="{StaticResource?BlackGlossyButton}"?Margin="1,0,0,0"?Foreground="White"??x:Name="wordBtn"?Click="wordBtn_Click">
?????????????????????????<StackPanel>
?????????????????????????????<Image?VerticalAlignment="Top"?HorizontalAlignment="Center"?Source="/SilverlightOOBDemo;component/Images/Word.png"?Margin="0,-5,0,0"?Stretch="None"?/>
?????????????????????????????<TextBlock?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,3,0,0"?Text="Word"?TextWrapping="Wrap"/>
?????????????????????????</StackPanel>
???????????????????</Button>
??????</StackPanel>
??????<TextBlock?Foreground="#8FFFFFFF"?Text="Office操作"?HorizontalAlignment="Center"?VerticalAlignment="Bottom"?Margin="2"?/>
??????</StackPanel>
?</Border>
~~~
對與三個應用分別添加其Click事件代碼。首先,我們先看看OutLook的COM調用,
~~~
??private?void?sendemailBtn_Click(object?sender,?RoutedEventArgs?e)
??{
??????????????using?(dynamic?outlook?=?AutomationFactory.CreateObject("Outlook.Application"))
??????????????{
??????????????????dynamic?mail?=?outlook.CreateItem(0);
??????????????????mail.To?=?"qq34506@hotmail.com";
??????????????????mail.Subject?=?"來自jv9的問候";
??????????????????mail.HTMLBody?=?"這封郵件是通過Silverlight發送的.";
??????????????????mail.Send();
?????????????????//mail.Display();??這里是顯示出發送郵件的Outlook窗口
?????????????}
?}
~~~
在建立Outlook實例后,我們可以使用Outlook.CreateItem來創建新的郵件實例,其中可以簡單的設置發送目的郵箱,標題,內容等。在代碼后面有mail.Send和Display兩個方法。其中如果調用Display,Silverlight會激活Outlook創建郵件窗口,然后用戶確認后發送郵件到目的郵箱。例如:

而調用mail.Send則會直接發送郵件到目的郵箱。而通常來說,我們建議使用mail.Display,讓用戶確認后再發送。


**Silverlight操作Office Word**
Silverlight操作Office Word比較簡單,首先我們添加Word的相應事件:
~~~
??private?void?wordBtn_Click(object?sender,?RoutedEventArgs?e)
??{
??????????????dynamic?word?=?AutomationFactory.CreateObject("Word.Application");
??????????????word.Visible?=?true;
??????????????dynamic?doc?=?word.Documents.Add();
??
?????????????string?Insertxt?=?"這是Silverlight操作Office?Word測試。歡迎大家訪問我的博客?http://jv9.cnblogs.com";
??????????????dynamic?range?=?doc.Range(0,?0);
??
?????????????range.Text?=?Insertxt;
}
~~~
在創建Word實例后,使用Documents.Add創建一個新的空文檔,然后,添加相關文檔或者圖片到Word中。其運行效果如下:

**Silverlight操作Office Excel**
相對上面兩個Office組件來講,Excel的使用較為復雜一點,這里我們來詳細演示Silverlight導出Excel的實例。
操作Excel不可缺少的是數據庫,作為演示實例,我使用Blend 4創建簡單的數據集合,使用Blend創建例程數據集合,我曾經在[Blend實例系列](http://www.cnblogs.com/jv9/archive/2010/03/26/1696594.html)中講過,這里我將簡單的演示,
首先使用Blend 4打開當前SilverlightOOBDemo項目,然后在右邊屬性欄,選擇Data,

這時會提示輸入SampleDataSource名稱:

點擊OK后,Blend 4將自動生成一個數據集合。

由于是Blend 4自動生成的,其中的String和Number都是隨機生成的,這些對于演示實例已經足夠了。

當SampleDataSource創建完成后,在SliverlightOOBDemo項目中,會創建一個SampleData目錄,其中包含了我們定義的數據源,

現在,需要在UI中創建一個Datagrid的控件,然后拖動右邊Data下SampleDataSource1下的Collection到Datagrid,進行數據綁定,這里我仍舊使用了Blend 4,所有控件和數據綁定,都是簡單的拖動即可實現。
~~~
?<sdk:DataGrid?x:Name="dgDemo"?Margin="10"?AutoGenerateColumns="False"?ItemsSource="{Binding?Collection}"?DataContext="{Binding?Source={StaticResource?SampleDataSource1}}"?>
??????<sdk:DataGrid.Columns>
?????????????<sdk:DataGridTextColumn?Binding="{Binding?Property1}"?Header="Property1"/>
?????????????<sdk:DataGridTextColumn?Binding="{Binding?Property2}"?Header="Property2"/>
?????????????<sdk:DataGridTextColumn?Binding="{Binding?Property3}"?Header="Property3"/>
??????</sdk:DataGrid.Columns>
?????????????????????????????
?</sdk:DataGrid>
~~~

以上設置,我們添加了Sample數據源,并且綁定數據到指定datagrid中,現在,可以設計Excel組件調用代碼,
~~~
??bool?firstTime?=?true;
??public?ObservableCollection<Item>?itemCollection?=?new?ObservableCollection<Item>();
??private?void?excelBtn_Click(object?sender,?RoutedEventArgs?e)
??{
??????????????dynamic?excel?=?AutomationFactory.CreateObject("Excel.Application");
??????????????excel.Visible?=?true;??
??????????????dynamic?workbook?=?excel.workbooks;
??????????????workbook.Add();
??????????????dynamic?sheet?=?excel.ActiveSheet;?
?????????????dynamic?cell?=?null;
?????????????int?i?=?1;
?????????????//?將數據傳輸到Excel
?????????????foreach?(Item?item?in?dgDemo.ItemsSource)
?????????????{
?????????????????itemCollection.Add(item);
?????????????????cell?=?sheet.Cells[i,?1];?//?列和行
?????????????????cell.Value?=?item.Property1;
?????????????????cell.ColumnWidth?=?25;
?????????????????cell?=?sheet.Cells[i,?2];
?????????????????cell.Value?=?item.Property3;
?????????????????i++;
?????????????}
?}
~~~
在上面代碼中,聲明一個Excel實例,然后通過循環輸入數據源到Excel實例Sheet中,從代碼中我們可以看出,輸出Excel是通過Cell進行操作的。
這里,我僅輸出了Property1和Property3兩列。這樣就簡單的實現了輸出Datagrid的數據到Excel了。

現在我們對當前的輸出Excel進行一些強化,輸入一個圖表功能。
對我們當前的代碼進行簡單的修改,添加如下代碼:
~~~
??bool?firstTime?=?true;
??public?ObservableCollection<Item>?itemCollection?=?new?ObservableCollection<Item>();
??private?void?excelBtn_Click(object?sender,?RoutedEventArgs?e)
??{
??????????????dynamic?excel?=?AutomationFactory.CreateObject("Excel.Application");
??????????????excel.Visible?=?true;??
??????????????dynamic?workbook?=?excel.workbooks;
??????????????workbook.Add();
??????????????dynamic?sheet?=?excel.ActiveSheet;?
?????????????dynamic?cell?=?null;
?????????????int?i?=?1;
?????????????//?將數據傳輸到Excel
?????????????foreach?(Item?item?in?dgDemo.ItemsSource)
?????????????{
?????????????????itemCollection.Add(item);
?????????????????cell?=?sheet.Cells[i,?1];?//?列和行
?????????????????cell.Value?=?item.Property1;
?????????????????cell.ColumnWidth?=?25;
?????????????????cell?=?sheet.Cells[i,?2];
?????????????????cell.Value?=?item.Property3;
?????????????????i++;
?????????????}
?????????????//?創建一個例程圖表
?????????????dynamic?sheetShapes?=?sheet.Shapes;
?????????????sheetShapes.AddChart(-4100,?200,?2,?400,?300);
?}
~~~
sheepShapes.AddChart創建一個新的圖表效果,其數據是綁定的dynamic sheet = excel.ActiveSheet??
這樣當我們再次運行輸出Excel時,即可得到如下結果:

這些功能的實現,完全是調用了Excel中提供的組件功能。
下面我們更進一步的完善Excel輸入功能,添加自動綁定更新事件。其目的是為了實現,當用戶輸出Excel后,修改Excel中數據,Silverlight的OOB應用中Datagrid同時也更新修改對應數據。
實現該需求,需要用到Excel的SheetChange事件。當用戶修改Excel中內容時,即激活該事件。首先,我們需要修改以上代碼,
~~~
??bool?firstTime?=?true;
??public?ObservableCollection<Item>?itemCollection?=?new?ObservableCollection<Item>();
??private?void?excelBtn_Click(object?sender,?RoutedEventArgs?e)
??{
??????????????dynamic?excel?=?AutomationFactory.CreateObject("Excel.Application");
??????????????excel.Visible?=?true;??
??????????????dynamic?workbook?=?excel.workbooks;
??????????????workbook.Add();
??????????????dynamic?sheet?=?excel.ActiveSheet;?
?????????????dynamic?cell?=?null;
?????????????int?i?=?1;
?????????????//?將數據傳輸到Excel
?????????????foreach?(Item?item?in?dgDemo.ItemsSource)
?????????????{
?????????????????itemCollection.Add(item);
?????????????????cell?=?sheet.Cells[i,?1];?//?列和行
?????????????????cell.Value?=?item.Property1;
?????????????????cell.ColumnWidth?=?25;
?????????????????cell?=?sheet.Cells[i,?2];
?????????????????cell.Value?=?item.Property3;
?????????????????i++;
?????????????}
?????????????//?創建一個例程圖表
?????????????dynamic?sheetShapes?=?sheet.Shapes;
?????????????sheetShapes.AddChart(-4100,?200,?2,?400,?300);
?????????????//?更新事件
?????????????if?(firstTime)
?????????????{
?????????????????excel.SheetChange?+=?new?SheetChangedDelegate(SheetChangedEventHandler);
????????????????string?sheetName?=?sheet.Name;
?????????????????firstTime?=?false;
?????????????}
}
~~~
為了完成SheetChange,我們需要添加相關事件委托。
~~~
delegate?void?SheetChangedDelegate(dynamic?excelSheet,?dynamic?rangeArgs);
~~~
其具體事件響應Handler為:
~~~
??????????private?void?SheetChangedEventHandler(dynamic?excelSheet,?dynamic?rangeArgs)
??????????{
??????????????dynamic?sheet?=?excelSheet;
??????????????string?sheetName?=?sheet.Name;
??????????????dynamic?range?=?rangeArgs;
??????????????dynamic?rowValue?=?range.Row;
??????????????ObservableCollection<Item>?entities?=?itemCollection;
??????????????Item[]?newEntities?=?new?Item[10];
?????????????dynamic?col2range?=?sheet.Range("B1:B10");
?????????????for?(int?i?=?0;?i?<?10;?i++)
?????????????{
?????????????????Item?newEntity?=?new?Item();
????????????????newEntity.Property1?=?entities[i].Property1;
?????????????????newEntity.Property2?=?entities[i].Property2;
?????????????????dynamic?item?=?col2range.Item(i?+?1);
?????????????????newEntity.Property3?=?Convert.ToInt32(item.Value);
?????????????????newEntities[i]?=?newEntity;
?????????????}
?????????????dgDemo.ItemsSource?=?newEntities;
?????????????dgDemo.SelectedIndex?=?Convert.ToInt32(rowValue)?-?1;
?????????}
~~~
這里,我設置操作sheet范圍為B1:B10,僅處理這個區域表格中數據綁定,而當excel中數據變化,則會查找對應表格到Datagrid的表格中進行更新。
其運行效果,當用戶修改Excel中的B1-B10中的數據,同時Datagrid會產生更新,并且Excel圖表也會產生更新效果。

上述介紹了Silverlight 4調用Office COM的具體方法,以及常用功能,大家可以在這個基礎上進行擴展,將其應用于自己的應用中。
[本篇源代碼下載](http://www.silverlightchina.net/resource/code/SilverlightOOBDemo0723.zip)
歡迎大家加入"專注Silverlight" 技術討論群:
32679955(六群)
23413513(五群)
32679922(四群)
100844510(三群)
37891947(二群)
22308706(一群)
?
?
- 前言
- Out of Browser開篇
- Out of Browser配置,安裝和卸載
- Out of Browser的自定義應用
- Out of Browser存取本地文件系統
- Out of Browser與COM的交互基礎
- Out of Browser與Office的互操作
- Out of Browser的Debug和Notifications窗口
- Out of Browser音樂播放器
- Out of Browser與COM互操作實例
- Out of Browser在線更新和Silent安裝
- Validation數據驗證開篇
- Validation數據驗證基礎屬性和事件
- Validation數據驗證DataAnnotation機制和調試技巧
- Validation服務器端異步數據驗證
- Validation客戶端同步數據驗證
- Validation用戶提交數據驗證捕獲
- Datagrid,Dataform數據驗證和ValidationSummary
- 自定義擴展Validation類,驗證框架的總結和建議
- Navigation導航框架開篇
- 理解Navigation導航框架Frame類
- 理解Navigation導航框架Page類
- Navigation導航框架URI映射機制
- Navigation導航框架傳遞參數