2009-08-30 48 views
18

我正在使用C#編寫Silverlight 3應用程序。我想允許用戶從Silverlight應用程序下載圖像。我正在使用SaveFileDialog來執行文件下載任務。流程如下:「對話框必須由用戶啓動。」在Silverlight 3中使用SaveFileDialog

  1. 用戶單擊SL應用程序中的下載按鈕。
  2. Web服務調用調用以從服務器獲取圖像
  3. OnCompleted web方法調用的異步事件處理函數被調用,並從服務器
  4. 內OnCompleted事件處理程序接收二進制圖像,SaveFileDialog提示用戶保存圖像到電腦。
  5. 將圖像流式傳輸到用戶硬盤上的文件。

我在從OnCompleted事件處理程序調用的函數中使用以下代碼來完成SaveFileDialog提示,然後流式傳輸到文件。

  SaveFileDialog dialog = new SaveFileDialog(); 
      dialog.Filter = "JPG Files|*.jpg" + "|All Files|*.*"; 
      bool? dialogResult = dialog.ShowDialog(); 

      if (dialogResult == true) 
      { 
       using (Stream fs = (Stream)dialog.OpenFile()) 
       { 
        fs.Write(e.Result, 0, e.Result.Length); 
        fs.Close(); 
       } 
      } 

SaveFileDialog會拋出錯誤「對話框必須是用戶啓動的。」當在上面的代碼中調用ShowDialog方法時。我在這裏可能會錯過什麼?如何克服這一點?

回答

19

此錯誤消息的含義是,您只能顯示SaveFileDialog以響應用戶啓動的事件,例如按鈕單擊。在你描述的例子中,你沒有顯示SaveFileDialog來響應點擊,而是響應已完成的http請求(這不是用戶啓動的事件)。因此,您需要做的是在http請求的Completed事件中向用戶顯示一些用戶界面,說明「下載完成,單擊此處將文件保存到您的計算機」,然後當用戶單擊在此消息上顯示SaveFileDialog。

+8

我得到了同樣的錯誤信息,試圖直接從Button_Click事件處理程序中使用SaveFileDialog,因爲我在調用新的SaveFileDialog()之前在方法中進行了一些驗證。下面的JumpingJezza的鏈接顯示了一個很好的例子,但看起來關鍵是在您的按鈕事件處理程序中將新的SaveFileDialog()作爲* first *行。之後,你可以看起來像做任何你喜歡的事情。 – Jedidja

+0

而「第一」行真的意味着_first_。我正在調試某人elses代碼和一個按鈕單擊事件處理程序中的註釋代碼塊導致提到的異常。 – faester

+2

我認爲這在saveialog打開之前是個相當麻煩的時間。如果在dialog.ShowDialog()發生錯誤之前放置斷點。請參閱http://dotnetslang.wordpress.com/2011/03/12/using-the-savefiledialog-dialogs-must-be-user-initiated-exception/ – maxence51

5

下載前先詢問一下,如何?從錯誤消息中可以看出,這是Silverlight希望你提示確保它知道用戶請求操作的方式,而不是用彈出窗口來抨擊用戶。

拋開Silverlight安全模型,我寧願不要等待下載完成,然後再問問它放在哪裏!

1

由於基思提到這是設計。 This教程給出了一個很好的例子,我使用代碼以「正確」的方式從服務器下載文件。 (也適用於Silverlight 4)

+1

您也可以在按鈕事件處理程序中創建SaveFileDialog。關鍵是確保構造函數是方法的第一行。 – Jedidja

1

我剛剛開始使用Silverlight 4,並且遇到同樣的問題。看起來,如果您手動創建事件處理程序,即使事件處理程序正在使用正確的參數處理按鈕單擊事件,但是如果您在Xaml中的按鈕上使用了「創建新事件處理程序」選項,也會引發安全異常在click事件下,具有相同代碼和參數的新事件處理函數現在可以工作....這是自從開始從WPF轉換到Silverlight以來我遇到過的許多「軟木」事件之一。

1
Private _syncContext As SynchronizationContext 
Private mBigStream As Stream 

Private Sub btnSave_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSave.Click 
    Try 
     Dim saveDialog As New SaveFileDialog 

     saveDialog.Filter = "Word |*.doc" 
     saveDialog.DefaultExt = ".doc" 

     If saveDialog.ShowDialog() Then 
      Try 
       mBigStream = saveDialog.OpenFile() 

       _syncContext = SynchronizationContext.Current 

       oWebService.GetReportAsync(Params, ... , _syncContext) 
      Catch ex As Exception 
       MessageBox.Show("File busy.") 
      End Try 
     End If 
    Catch ex As Exception 
     LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) 
    End Try 
End Sub 

Private Sub oWebService_GetReportCompleted(sender As Object, e As MainReference.GetReportCompletedEventArgs) Handles oWebService.GetReportCompleted 
    Try 
     ' e.Result is byte() 

     If e.Result IsNot Nothing Then 
      If e.Result.Count > 0 Then 
       _syncContext.Post(Sub() 
             Try 
              mBigStream.Write(e.Result, 0, e.Result.Length) 

              mBigStream.Flush() 
              mBigStream.Close() 

              mBigStream.Dispose() 

              mBigStream = Nothing 
             Catch ex As Exception 
              LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) 
             End Try 
            End Sub, Nothing) 

       _syncContext = Nothing 
      End If 
     End If 
    Catch ex As Exception 
     LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) 
    End Try 
End Sub 
+2

你能否詳細解釋你的答案?答案應該提供方向,而不僅僅是c/p代碼。 – CodeMouse92

相關問題