0

特定の請求書データを WPF VB.NET アプリから Word にロードするプロセスを示すダイアログ ボックスを作成しようとしています。問題は、変更を表示するために WPF UI が更新されていないことです。

WPF コードは次のとおりです。

    <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" >
        <TextBlock Name="StatusDisplayTextBlock" Text="Printing 30 of 40 to document......" FontSize="20"/>
        <ProgressBar Name="PrintProgressBar1" Height="30" Width="400" Margin="0,10,0,0"/>
    </StackPanel>

VB.NET コード:

Imports Microsoft.Office.Interop

Public Class PrintingToDocx
    Dim IsWorkDone As Boolean = False
    Public Enum BillPrintMode
        InOne = 0
        Seperate = 1
    End Enum

    Private BrowserBills As New List(Of Classes.BillsNS.BilBrowserClass)
    Private Bills As New List(Of Classes.BillsNS.BillClass)
    Private PrintMode As BillPrintMode

    Private Sub PrintingToDocx_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
        If IsWorkDone = False Then
            e.Cancel = True
        End If
    End Sub

    Public Sub New(ByVal BrowserBills As List(Of Classes.BillsNS.BilBrowserClass), ByVal Mode As BillPrintMode)
        InitializeComponent()
        Me.BrowserBills = BrowserBills
        PrintMode = Mode
    End Sub

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        GetBills()
        If PrintMode = BillPrintMode.InOne Then
            PrintInOne()
            ' IsWorkDone = True
        Else
            Dim count As Integer = 0
            For Each k In Bills
                count = count + 1
                StatusDisplayTextBlock.Text = "Writing Bill " & count & " of " & Bills.Count & " to WORD....."
                DataAccessModuleNS.Reports.PrintaBill(k)
            Next
            IsWorkDone = True
        End If
        Me.Close()
    End Sub

    Private Sub GetBills()
        Me.Focus()
        StatusDisplayTextBlock.Text = "Reading Bills Data...."
        Dim count As Integer = 1
        For Each k In BrowserBills
            Bills.Add(DataAccessModuleNS.Bills.GetBill(k.ID.ToString))
            StatusDisplayTextBlock.Text = "Reading Bill " & count & " of " & BrowserBills.Count & "...."
            'count = count + 1
            count += 1
        Next
    End Sub

    Private Sub PrintInOne()
        Try
            StatusDisplayTextBlock.Text = "Writing Bill " & "0" & " of " & Bills.Count & " to WORD....."

            Dim oWord As Word.Application
            Dim oDoc As Word.Document
            Dim oTable As Word.Table

            Me.Focus()
            'Start Word and open the document template.
            oWord = CreateObject("Word.Application")
            oWord.Visible = False
            oDoc = oWord.Documents.Add
            Dim countBills As Integer = 0
            For Each Bill In Bills
                'To Addressing Fields
                countBills = countBills + 1
                StatusDisplayTextBlock.Text = "Writing Bill " & countBills & " of " & Bills.Count & " to WORD....."

    End Sub
End Class

問題は次のようなものです: 機能は正常に動作していますが、すべての処理が完了するまで UI が表示されません。以下はWordへの処理時のタスクバーのサンプル画像です。 ここに画像の説明を入力

作業が完了すると、次のように正常に動作しています。

以下はレポートです

ここに画像の説明を入力

編集:バックグラウンドワーカーを使用しましたが、進行状況が変更され、UI スレッドで TextBlock を更新しようとすると、別のスレッドでアクションを実行できないというエラーが発生するという問題があります。以下は、ProgressChanged イベントで使用したコードです。

Private Sub BackgroundWorker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
    'Throw New NotImplementedException
    StatusDisplayTextBlock.Text = e.UserState
End Sub

UI スレッドの更新方法を教えてください。

4

1 に答える 1

0

UIスレッドからロジック操作を移動する必要があります...

最善の解決策は、Backgroundworkerクラスを使用して、すべての操作をUIから分離することです。それに関する良いチュートリアルはここにあります[リンク]

変更によって.NET4.5を使用できる場合は、Async-Awaitパターン[ AsyncinVB ]を簡単に使用できます。

于 2012-12-22T12:59:58.343 に答える