WPF: Updating visibility of controls not updating the screen
I will preface this by stating that I am new to WPF programming and may be making multiple errors. Any insight that can be provided to help me improve in my skills are greatly appreciated.
I am working with a WPF application and am looping through a list of objects that contain properties that describe a document that should be built on the fly and automatically printed. I am attempting to display a small grid in the interface that shows the document being built before it is printed. This serves two purposes: one, it allows the user to see work being done by the application. Two, it renders the items on the screen so that I can then have something to actually print since WPF appears to not be able to load an image for printing dynamicaly without displaying it on the screen. In my code, I am setting the various elements in the grid and setting the visibility to visible. However, the UI is not updating and the printed document doesn't look as intended since the image never shows up on the screen.
Here is the XAML that I have set up
<Grid x:Name="LayoutRoot" Background="Black">
<Grid Name="previewGrid" Grid.Row="1" Grid.Column="1" Background="White" Visibility="Hidden">
<Canvas Name="pageCanvas" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid Name="pageGrid" Width="163" Height="211">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="81.5"></ColumnDefinition>
<ColumnDefinition Width="81.5"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Name="copyright" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Bottom"></TextBlock>
<Image Name="pageImage" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
</Grid>
</Canvas>
.....canvas for pages 2-4 not shown but structure is the same as for pageGrid.....
</Grid>
</Grid>
</Window>
Here is the code behind that is supposed to set the elements.
Dim bmp as new Bitmapimage
previewGrid.Visibility = Windows.Visibility.Visible
pageURI = New Uri(pageCollection(i).iamgeURL, UriKind.Absolute)
pageGrid.Visibility = Windows.Visibility.Visible
bmp.BeginInit()
bmp.UriSource = cardURI
bmp.EndInit()
pageImage.Source = bmp
copyright.Text = copyrightText
cardPreviewGrid.UpdateLayout()
' More code that prints the visual element pageCanvas
previewGrid.Visibility = Windows.Visibility.Hidden
The code in codebehind loops through a number of times depending on how many different documents the user prints. Basically it builds a visual element for a page, prints an XPS version of it and then builds the next page and prints it, etc. Once all pages have been processed, the job is actually sent to the printer. The only purpose of this application is to let the user print these documents so there is not other task that they can do in the application while the documents print. I thought that putting this task in a background thread would help to update the UI but since I am trying to manipulate items directly on the UI thread it would appear开发者_Python百科 that this option won't work for me. What am I doing wrong here and how can I improve the code so that I can get the behavior that I am trying to achieve?
I can't speak to the issues of printing, but your UI's not going to get updated at all while the UI thread is executing this code. It can't; it's busy executing this code.
If you want to dynamically update the UI while a long-running task is executed, you need to execute the task on a background thread and periodically use Invoke()
to update objects on the UI thread - or, for a saner, easier to manage experience, use a BackgroundWorker
.
There may be some totally different issue going on as well; I can't really tell from what you've posted. But I'm pretty sure that's a big part of your problem.
Edit
Jeez, maybe I should read your entire question, not just the bits of it that initially get my attention.
Okay, I don't know how viable this approach will be in your situation, but: The BackgroundWorker
can raise events as its task runs; if you call ReportProgress
, it will raise the ProgressChanged
event. The ProgressChanged
event runs on the UI thread, and I believe that the DoWork
method blocks and waits until the event handlers are done.
What's a little odd about your situation is that the background process isn't really doing anything. Your DoWork
method would basically just keep calling ReportProgress
until it was done.
Another way to do this would be to use a timer. Put the images that you want to update the UI (or objects that load the images) into a queue, and set a timer so that its Tick
event handler processes the first item in the queue. The event handler would stop the timer, process the current work item, and then start the timer again with an interval of a tenth of a second. The end result would be that after every image was processed, the UI would have a tenth of a second to process any pending UI events - like drawing the image on the screen.
精彩评论