C# Windows Phone 8 WP8,擷取UIElement轉換成WriteableBitmap並存入IsolatedStorageFile,解決控制項全部擠一起的問題。

  • 6058
  • 0
  • C#
  • 2015-06-10

一般我們在撰寫Windows Phone App的時候有時會需要擷取螢幕上的控制項轉換成圖片,當我們想要在背景執行並生成圖片給使用者時,就必須用程式碼動態產生的方式來達成,但是怎麼邏輯上沒有錯,可是生成的圖片卻跟理想狀態不一樣呢?

本篇文章將引導您擷取UI轉換成WriteableBitmap並存入IsolatedStorage,解決控制項全部擠一起的問題。

一般我們在撰寫Windows Phone App的時候有時會需要擷取螢幕上的控制項轉換成圖片,當我們想要在背景執行並生成圖片給使用者時,就必須用程式碼動態產生的方式來達成,但是怎麼邏輯上沒有錯,可是生成的圖片卻跟理想狀態不一樣呢?

 

本篇文章將引導您擷取UI轉換成WriteableBitmap並存入IsolatedStorage,解決控制項全部擠一起的問題。

 

首先我們先學習一下如何將舞台上的UIElement擷取下來並存放在IsolatedStorage

 

在Xaml中必須定義控制項的名字,以便在程式碼中取用,並依照個人需求放入控制項:

 

   1:  <Grid x:Name="LayoutRoot" Background="Transparent">
   2:      ........
   3:  </Grid>

 

再來就是程式碼的部分:

 

   1:  public MainPage()
   2:  {
   3:      InitializeComponent();
   4:              
   5:      //必須在控制項已經繪製完成的時候動作,否則會擷取不到圖片
   6:      this.LayoutUpdated += (sender, e) => {
   7:          //將控制項轉換為WriteableBitmap
   8:          WriteableBitmap UI_Image = new WriteableBitmap(LayoutRoot, null);
   9:          //轉換為JPG並寫入IsolatedStorageFile
  10:          Write_Bitmap_TO_Isolate(UI_Image, "QQ.jpg");
  11:      };
  12:  }
  13:   
  14:  //將WriteableBitmap轉換為JPG並寫入IsolatedStorageFile
  15:  private void Write_Bitmap_TO_Isolate(WriteableBitmap WriteBitmap, string FileName)
  16:  {
  17:      try
  18:      {
  19:   
  20:          using (IsolatedStorageFile tStorage = IsolatedStorageFile.GetUserStoreForApplication())
  21:          {
  22:              var isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
  23:              //如果目標檔案已經存在,則刪除檔案
  24:              if (isolatedStorage.FileExists(FileName))
  25:              {
  26:                  isolatedStorage.DeleteFile(FileName);
  27:                  Debug.WriteLine("目標檔案存在  刪除");
  28:              }
  29:              //創建檔案
  30:              IsolatedStorageFileStream fileStream = isolatedStorage.CreateFile(FileName);
  31:              //寫入檔案
  32:              WriteBitmap.SaveJpeg(fileStream, WriteBitmap.PixelWidth, WriteBitmap.PixelHeight, 0, 100);
  33:              //關閉IO
  34:              fileStream.Close();
  35:              fileStream.Dispose();
  36:              tStorage.Dispose();
  37:   
  38:          }
  39:      }
  40:      catch (Exception ex)
  41:      {
  42:          Debug.WriteLine("例外狀況:"+ex.Message);
  43:      }
  44:   
  45:  }

 

如此一來我們可以很輕易地擷取到控制項的畫面,

查看IsolatedStorageFile請參閱:

[Windows Phone 8 | Dev Tool]_介紹並解決Windows Phone Power Tools找不到SmartDevice.Connectivity的問題

Windows Phone 8 使用 IsoStoreSpy 查看 IsolatedStorageFile

 

image

 

用Xaml來做卻是相當的簡單,但是用C#程式碼來動態產生的UIElement,可能就會遇到一些事情了,

 

首先根據需求預想我們要的版面:

image        image

架構如右圖,想好版面後可以開始來用程式碼動態產生囉,

並用相同的方法轉換成WriteableBitmap並存入IsolatedStorage!!

動態產生控制項請參閱:

C# Windows 8,Windows Phone 8 WP8,使用程式碼動態產生Chart長條圖,不用Telerik UI也能做。

C# Windows 8,Windows Phone 8 WP8,使用程式碼動態產生ScrollViewer,並放入可捲動的資料。

C# Windows 8,Windows Phone 8 WP8,使用程式碼動態產生Grid。

C# Windows 8,Windows Phone 8 WP8,使用程式碼動態產生StackPanel。

[筆記]C# Windows Phone 8 WP8 開發,找回StackPanel底下Orientation消失的屬性。

 

   1:  double TD_R = 1234;
   2:  double TM_R = 5678;
   3:  string account = "一起做運動";
   4:   
   5:  //====================動態產生的UIElement====================
   6:  Grid Grid_Root = new Grid() { 
   7:      Width = 336, 
   8:      Height = 336
   9:  };
  10:  Grid_Root.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
  11:  Grid_Root.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
  12:  Grid_Root.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
  13:  Grid_Root.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
  14:   
  15:  StackPanel STP_Revenue = new StackPanel()
  16:  {
  17:      Orientation = System.Windows.Controls.Orientation.Vertical,
  18:      VerticalAlignment=VerticalAlignment.Top,
  19:      HorizontalAlignment=HorizontalAlignment.Left
  20:  };
  21:   
  22:  StackPanel STP_Title=new StackPanel(){
  23:      Orientation = System.Windows.Controls.Orientation.Horizontal,
  24:      Margin=new Thickness(10,10,10,10)
  25:  };
  26:  Image image=new Image(){
  27:      Height = 20,
  28:      Width = 20,
  29:      Stretch = Stretch.Uniform,
  30:      VerticalAlignment = VerticalAlignment.Center,
  31:      Source = new BitmapImage(new Uri("/Assets/ApplicationIcon.png", UriKind.RelativeOrAbsolute)),
  32:      Margin = new Thickness(10)};
  33:  TextBlock Text_Title=new TextBlock(){
  34:      Foreground=new SolidColorBrush(Colors.White),
  35:      FontSize=20,
  36:      VerticalAlignment=VerticalAlignment.Center,
  37:      Text="健康口訣"
  38:  };
  39:  STP_Title.Children.Add(image);
  40:  STP_Title.Children.Add(Text_Title);
  41:   
  42:  TextBlock Text_Account = new TextBlock()
  43:  {
  44:      Foreground = new SolidColorBrush(Colors.White),
  45:      FontSize = 20,
  46:      VerticalAlignment = VerticalAlignment.Center,
  47:      Text = account
  48:  };
  49:   
  50:  TextBlock Text_TM = new TextBlock() {
  51:      Foreground = new SolidColorBrush(Colors.White),
  52:      FontSize = 20,
  53:      VerticalAlignment = VerticalAlignment.Center,
  54:      Text = ""+TM_R
  55:  };
  56:   
  57:  TextBlock Text_TD = new TextBlock()
  58:  {
  59:      Foreground = new SolidColorBrush(Colors.White),
  60:      FontSize = 20,
  61:      VerticalAlignment = VerticalAlignment.Center,
  62:      Text = "" + TD_R
  63:  };
  64:   
  65:  Grid.SetRow(STP_Title, 0);
  66:  Grid.SetRow(Text_Account, 1);
  67:  Grid.SetRow(Text_TM, 2);
  68:  Grid.SetRow(Text_TD, 3);
  69:  Grid_Root.Children.Add(STP_Title);
  70:  Grid_Root.Children.Add(Text_Account);
  71:  Grid_Root.Children.Add(Text_TM);
  72:  Grid_Root.Children.Add(Text_TD);
  73:   
  74:  //將UIElement轉換為WriteableBitmap並寫入IsolatedStorageFile
  75:  WriteableBitmap UI_Image = new WriteableBitmap(Grid_Root, null);
  76:  Write_Bitmap_TO_Isolate(UI_Image,"QQ.jpg");

 

再去查看一下IsolatedStorageFile裡的檔案…

挖哩...全部擠成一塊啊!

 

image

 

這下可好...交到客戶手上又要變成垃圾中的垃圾了....

這其實是因為使用C#動態產生控制項時,雖然已經控制項的屬性還有子項目已經佈署完成,

可是控制項並尚未被繪製,所以才會看起來全部擠成一起。

好吧既然知道原因了,那就開始動手修改程式碼吧!

其實只要改一小小段程式碼就可以囉!大體上程式碼的架構還是沒有錯的,只是必須讓控制項先繪製,

再儲存到WriteableBitmap並存入IsolatedStorage!!

 

將以下程式碼刪除:

 

   1:  WriteableBitmap UI_Image = new WriteableBitmap(Grid_Root, null);
   2:  Write_Bitmap_TO_Isolate(UI_Image,"QQ.jpg");

 

換成:

 

   1:  //更新配置並指定大小
   2:  Grid_Root.Measure(new Size(336, 336));
   3:  //放置子項目,以及判斷 UIElement 的大小
   4:  Grid_Root.Arrange(new Rect(0, 0, 336, 336));
   5:  //給定WriteableBitmap要繪製的大小
   6:  WriteableBitmap UI_Image = new WriteableBitmap(336, 336);
   7:  UI_Image.Render(Grid_Root, null);
   8:  //繪製
   9:  UI_Image.Invalidate();
  10:  //將UIElement轉換為WriteableBitmap並寫入IsolatedStorageFile
  11:  Write_Bitmap_TO_Isolate(UI_Image, "QQ.jpg");

 

再運行一次

終於得到我們想要的結果了 呼~

image

 

如此一來就學會了擷取UIElement轉換成WriteableBitmap並存入IsolatedStorageFile,解決控制項全部擠一起的問題。

 

References :

UIElement.Measure
UIElement.Arrange
UIElement.Invalidate
WriteableBitmap

 

文章中的敘述如有觀念不正確錯誤的部分,歡迎告知指正 謝謝
轉載請註明出處,並且附上本篇文章網址 !  感謝。

SUKI

HOLIESTAR