在前文,我們講述了Silverlight Out of Browser的基礎以及自定義模式應用。本篇,我們將講述Silverlight Out of Browser應用的重點 - 創建可信任應用,也稱為Trusted Application. 早在Silverlight 3,Silverlight Out of Browser的功能由于權限的限制無法很好的滿足用戶的正常存取需求,僅能實現將Web應用脫離瀏覽器。而在Silverlight 4中,通過提升應用信任權限,大大增強了Silverlight Out of Browser的功能,在權限允許的情況下,用戶可以自由有訪問本地目錄,也可以執行本地應用程序,另外通過調用COM組件,實現更多更強大的本地應用操作。下面我們將實例講述Silverlight Out of Browser可信任應用 - 存取本地文件系統。
本篇中,我們將基于上篇教程提供的項目SilverlightOOBDemo進行演示操作。
首先需要確認SilverlightOOBDemo項目允許用戶提升應用信任權限。這樣,OOB應用將被允許訪問用戶本地資源。

Silverlight 4對于本地文件夾的存取,并非代表存取所有本地磁盤目錄,目前為止,Silverlight 4 API僅支持存取“我的文檔”,“我的音樂”,“我的圖片”和“我的視頻”目錄以及“Program Files”和“Cookies”目錄,而如果想對所有磁盤目錄進行訪問,則需要使用COM功能進行操作,我們將在下篇講述,本篇將著重講述Silverlight 4 API對“我的”系列目錄的操作方法。
在實現具體功能前,首先需要為項目添加兩個新文件,
一個是資源文件Resources.xaml,該資源文件引用自開源控件BlackLight資源樣式,主要目的是為了創建新按鈕演示效果,如下圖:

另一個是小圖片控件ThumbImage.xaml,該文件是用于載入“我的圖片”目錄后的圖片略縮圖,其代碼較為簡單,
~~~
??<UserControl?x:Class="SilverlightOOBDemo.ThumbImage"
??????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"
??????d:DesignHeight="300"?d:DesignWidth="400">
?????<Grid?x:Name="LayoutRoot"?Margin="10">
?????????<Image?x:Name="ThumbnailImage"?Height="145"?Width="225"?/>
?????</Grid>
?</UserControl>
~~~
~~~
??namespace?SilverlightOOBDemo
??{
??????public?partial?class?ThumbImage?:?UserControl
??????{
??????????private?Image?_OriginalImage;
??????????public?Image?OriginalImage?
??????????{?
??????????????get?
??????????????{
?????????????????return?_OriginalImage;?
?????????????}?
?????????????set?
?????????????{
?????????????????this._OriginalImage?=?value;
?????????????????ThumbnailImage.Source?=?new?WriteableBitmap(_OriginalImage,?null);?
?????????????}?
?????????}
?????????public?ThumbImage()
?????????{
?????????????InitializeComponent();
?????????}
?????}
?}
~~~
為了能夠激活存取事件,我們需要在OutofBrowserMainpage主窗口頁面添加按鈕控件,其樣式調用自資源文件Resources.xaml,對于資源樣式調用,這里不再贅述,如果不明白的,請看“[Expression Blend實例中文教程系列文章](http://www.cnblogs.com/jv9/archive/2010/04/11/1709527.html)”

~~~
??<StackPanel?x:Name="toolbar"?Background="#FF3A3A3A"?Grid.ColumnSpan="2"?Orientation="Horizontal"?Margin="0,0,0,1"?Grid.Row="0"?>
??????????????????????????<Border?BorderBrush="{StaticResource?GlossyBlack_StrokeGradient}"?BorderThickness="1"?CornerRadius="2"?Margin="1"?Padding="0,1,1,1">
??????????????????????????????<StackPanel>
??????????????????????????????????<StackPanel?Orientation="Horizontal">
??????????????????????????????????????<Button?Width="56"?Height="80"?Style="{StaticResource?BlackGlossyButton}"?Margin="1,0,0,0"?Foreground="White"?x:Name="openFileBtn"?Click="openFileBtn_Click"> ?????????????????????????????????????????<Button.Content>
??????????????????????????????????????????????<StackPanel>
??????????????????????????????????????????????????<Image?VerticalAlignment="Top"?HorizontalAlignment="Center"?Source="/SilverlightOOBDemo;component/Images/Open.png"?Margin="0,-5,0,0"?Stretch="None"?/>
??????????????????????????????????????????????????<TextBlock?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,3,0,0"?Text="瀏覽"?TextWrapping="Wrap"/>
?????????????????????????????????????????????</StackPanel>
?????????????????????????????????????????</Button.Content>
?????????????????????????????????????</Button>
?????????????????????????????????</StackPanel>
?????????????????????????????</StackPanel>
?????????????????????????</Border>
?????????????????????????<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="aboutBtn"?Click="">
?????????????????????????????????????????<Button.Content>
?????????????????????????????????????????????<StackPanel>
?????????????????????????????????????????????????<TextBlock?VerticalAlignment="Top"?HorizontalAlignment="Center"?Text="?"?FontSize="20"?FontWeight="Bold"?Foreground="DarkCyan"??Margin="0,-5,0,0"?/>
?????????????????????????????????????????????????<TextBlock?VerticalAlignment="Bottom"?HorizontalAlignment="Center"?Margin="0,3,0,0"?Text="幫助"?TextWrapping="Wrap"/>
????????????????????????????????????????????</StackPanel>
?????????????????????????????????????????</Button.Content>
?????????????????????????????????????</Button>
?????????????????????????????????</StackPanel>
?????????????????????????????</StackPanel>
????????????????????????</Border>
?????????????????????</StackPanel>
~~~
同時,為了能夠載入本地“我的圖片”目錄中的圖片文件,我們需要在OutofBrowserMainpage中使用一個ListBox控件,載入上面我們創建的ThumbImage控件來顯示,所有圖片略縮圖列表,
~~~
?<ListBox?Grid.Column="0"??x:Name="lsMyPictures"?SelectionMode="Single"?Style="{StaticResource?GlossyBlackListBox}"?ItemContainerStyle="{StaticResource?ListBoxItemStyle}"?BorderBrush="Transparent"?Background="Transparent"?ScrollViewer.HorizontalScrollBarVisibility="Auto"?ScrollViewer.VerticalScrollBarVisibility="Auto"?Margin="3,10,0,30"?></ListBox>
~~~
現在,我們可以為openfilebtn按鈕控件創建事件,使其響應用戶操作,打開對應目錄進行文件瀏覽
~~~
??????????private?void?openFileBtn_Click(object?sender,?RoutedEventArgs?e)
??????????{
??????????????if?(Application.Current.HasElevatedPermissions)
??????????????{
??????????????????var?imageFiles?=?Directory.EnumerateFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),?"*.jpg",?SearchOption.AllDirectories);
??????????????????foreach?(var?imagePath?in?imageFiles)
??????????????????{
??????????????????????AddImageToList(new?FileInfo(imagePath));
??????????????????}
?????????????}
?????????}
~~~
在上面代碼中,如果用戶已經提升了OOB應用權限(Application.Current.HasElevatedPermissions),將通過Environment中的GetFolderPath方法獲取到本地“My..”目錄下的文件,其中Environment.SpecialFolder可以設定特殊目錄。更多詳細,[請看MSDN解釋](http://msdn.microsoft.com/en-us/library/system.environment.specialfolder(VS.95).aspx)。

在上面代碼中,有一個方法AddImageToList,將文件路徑信息讀取,然后將圖片文件信息進行綁定到ListBox。
~~~
??????????private?void?AddImageToList(FileInfo?fileinfo)
??????????{
??????????????FileStream?fileStream?=?fileinfo.OpenRead();
??????????????Image?img?=?new?Image();
??????????????BitmapImage?bi?=?new?BitmapImage();
??????????????bi.SetSource(fileStream);
??????????????img.Margin?=?new?Thickness(5d);
??????????????img.Stretch?=?Stretch.UniformToFill;
??????????????img.Source?=?bi;
?????????????try?{?img.Tag?=?fileinfo.FullName;?}
?????????????catch?{?}
?????????????ThumbImage?thumbnail?=?new?ThumbImage();
?????????????thumbnail.OriginalImage?=?img;
?????????????lsMyPictures.Items.Add(thumbnail);
?????????}
~~~
在讀取“我的圖片”目錄信息后,將各個圖片載入到ThumbImage控件中,然后使用ListBox承載各個圖片,這樣也就完成了OOB應用對本地目錄的瀏覽。其效果如下:

通過以上的代碼,我們可以快速修改,瀏覽“我的文檔”,“我的音樂”和“我的視頻”等目錄;在OutofBrowserMainPage頁面添加代碼:
~~~
<ListBox?Grid.Column="1"??x:Name="lsMyDocuments"?SelectionMode="Single"?Style="{StaticResource?GlossyBlackListBox}"?ItemContainerStyle="{StaticResource?ListBoxItemStyle}"?BorderBrush="Transparent"?Background="Transparent"?ScrollViewer.HorizontalScrollBarVisibility="Auto"?ScrollViewer.VerticalScrollBarVisibility="Auto"?Margin="3,10,0,30"?></ListBox>
~~~
~~~
?private?void?AddDocToList()
?????????{
?????????????var?path?=?Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); ?????????????lsMyDocuments.ItemsSource?=?System.IO.Directory.EnumerateFiles(path);
?????????}
~~~
然后在openFileBtn_Click事件中調用AddDocToList();即可獲取到“我的文檔”文件列表, 其他目錄與其類似,就不再做代碼演示,大家可以自己嘗試,如果遇到問題,我們可以一起討論 。

看到這里,有的朋友可能會問,既然已經可以實現瀏覽本地目錄功能,是不是也應該可以對本地目錄文件進行操作呢?答案是肯定的。當OOB應用獲取到權限提升后,則可以使用File類對文件進行操作,例如,移動文件,刪除文件等。對目前的項目我們進行簡單的修改,演示如何將“我的文檔”目錄的文件,移動到“我的音樂”目錄中,并且刪除源目錄的相同文件,
首先在OutofBrowserMainPage.xaml頁面添加一個新的ListBox,承載“我的音樂”目錄文件;
~~~
?<StackPanel?Orientation="Vertical"?Width="200">
?????????????????????????????????????<TextBlock?Text="我的音樂"?Foreground="White"?VerticalAlignment="Center"?HorizontalAlignment="Center"/>
?????????????????????????????????????<ListBox?x:Name="lsMyMusics"?SelectionMode="Single"?Style="{StaticResource?GlossyBlackListBox}"?ItemContainerStyle="{StaticResource?ListBoxItemStyle}"?BorderBrush="Transparent"?Background="Transparent"?ScrollViewer.HorizontalScrollBarVisibility="Auto"?ScrollViewer.VerticalScrollBarVisibility="Auto"?Margin="3,10,0,30"></ListBox>
?????????????????????????????????</StackPanel>
~~~
在后臺代碼添加,瀏覽載入“我的音樂”目錄;
~~~
??private?void?AddMusicToList()
??????????{
??????????????var?path?=?Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
??????????????lsMyMusics.Items.Clear();
??????????????DirectoryInfo?myDirectory?=?new?DirectoryInfo(path);
??????????????foreach?(FileInfo?file?in?myDirectory.EnumerateFiles())
??????????????{
??????????????????lsMyMusics.Items.Add(file);
??????????????}
?????????}
~~~
簡單修改“我的文檔”ListBox代碼,和后臺代碼:
~~~
?<StackPanel?Orientation="Vertical"?Width="200">
?????????????????????????????????????<TextBlock?Text="我的文檔"?Foreground="White"?VerticalAlignment="Center"?HorizontalAlignment="Center"/>
?????????????????????????????????????<ListBox?x:Name="lsMyDocuments"?SelectionMode="Single"?Style="{StaticResource?GlossyBlackListBox}"?ItemContainerStyle="{StaticResource?ListBoxItemStyle}"?BorderBrush="Transparent"?Background="Transparent"?ScrollViewer.HorizontalScrollBarVisibility="Auto"?ScrollViewer.VerticalScrollBarVisibility="Auto"?Margin="3,10,0,30"></ListBox> ?????????????????????????????????</StackPanel>
~~~
~~~
??private?void?AddDocToList()
??????????{
??????????????var?path?=?Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
??????????????lsMyDocuments.Items.Clear();
??????????????DirectoryInfo?myDirectory?=?new?DirectoryInfo(path);
??????????????foreach?(FileInfo?file?in?myDirectory.EnumerateFiles())
??????????????{
??????????????????lsMyDocuments.Items.Add(file);
??????????????}
?????????????//lsMyDocuments.ItemsSource?=?System.IO.Directory.EnumerateFiles(path);
?????????}
~~~
運行后即可得到如下效果:

下面我們想實現,點擊按鈕事件后,將“我的文檔”目錄中的選中文件,移動到“我的音樂”目錄中,
首先,在應用的ToolBar中添加一個移動按鈕moveFileBtn

實現moveFileBtn被點擊后,移動文件到“我的音樂”目錄,
~~~
??private?void?moveFileBtn_Click(object?sender,?RoutedEventArgs?e)
??????????{
??????????????FileInfo?selectedFile?=?(FileInfo)lsMyDocuments.SelectedValue;
??????????????string?path?=?Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
??????????????string?formatPath?=?string.Format("{0}//{1}",?path,?selectedFile.Name);
??????????????if?(!File.Exists(formatPath))
??????????????{
??????????????????File.Move(selectedFile.FullName,?formatPath);
??????????????????File.Delete(selectedFile.FullName);
?????????????}
?????????????LoadFiles();
?????????}
?????????private?void?LoadFiles()
?????????{
?????????????AddDocToList();
?????????????AddMusicToList();
?????????}
~~~
這里我們用的是最基本的File文件類操作文件的移動和刪除,當然,這需要OOB應用被提升信任權限后,才可以操作,否則,將提示權限錯誤。
這樣,我們就可以查看演示了,當運行應用后,“我的文檔”和“我的音樂”兩個目錄將被載入文件列表,選中“我的文檔”中任一文件,然后點擊“移動”按鈕,就會發現該文件被移動到“我的音樂”目錄中,而在“我的文檔”中的源文件已經被刪除。

通過上文,我們可以了解到Silverlight Out of Browser的可信任應用對本地目錄和文件的操作方法以及基本API的用法,下一篇,我們將通過另外一個實例演示更多Out of Browser的可信任應用的強大功能。
注:本篇部分代碼是參考Silverlight開源項目。
[本篇源代碼下載](http://silverlightchina.net/uploads/soft/100716/1-100G6162537.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導航框架傳遞參數