WPF: обновление видимости элементов управления без обновления экрана - PullRequest
1 голос
/ 19 марта 2010

Я предвосхищу это, заявив, что я новичок в программировании WPF и могу сделать несколько ошибок. Будем очень благодарны за любую информацию, которая поможет мне улучшить свои навыки.

Я работаю с приложением WPF и перебираю список объектов, которые содержат свойства, описывающие документ, который должен быть создан на лету и автоматически распечатан. Я пытаюсь отобразить небольшую сетку в интерфейсе, который показывает документ, который создается до его печати. Это служит двум целям: во-первых, оно позволяет пользователю видеть работу, выполняемую приложением. Во-вторых, он отображает элементы на экране, чтобы у меня была возможность что-то напечатать, так как WPF, похоже, не может загрузить изображение для динамической печати, не отображая его на экране. В моем коде я устанавливаю различные элементы в сетке и устанавливаю видимость видимой. Однако пользовательский интерфейс не обновляется, и напечатанный документ выглядит не так, как задумано, поскольку изображение никогда не появляется на экране.

Вот XAML, который я настроил

<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>

Вот код, который должен установить элементы.

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

Код в codebehind циклически повторяется несколько раз в зависимости от того, сколько разных документов печатает пользователь. По сути, он создает визуальный элемент для страницы, печатает его версию XPS, а затем создает следующую страницу, печатает ее и т. Д. После обработки всех страниц задание фактически отправляется на принтер. Единственная цель этого приложения - дать пользователю возможность распечатать эти документы, чтобы не было другой задачи, которую они могут выполнить в приложении во время печати документов. Я думал, что помещение этой задачи в фоновый поток поможет обновить пользовательский интерфейс, но, поскольку я пытаюсь манипулировать элементами непосредственно в потоке пользовательского интерфейса, может показаться, что эта опция не будет работать для меня. Что я здесь не так делаю и как я могу улучшить код, чтобы получить поведение, которого я пытаюсь достичь?

1 Ответ

0 голосов
/ 19 марта 2010

Я не могу говорить о проблемах печати, но ваш пользовательский интерфейс вообще не будет обновляться, пока поток пользовательского интерфейса выполняет этот код. Не может; он занят выполнением этого кода.

Если вы хотите динамически обновлять пользовательский интерфейс во время выполнения длительной задачи, вам нужно выполнить задачу в фоновом потоке и периодически использовать Invoke() для обновления объектов в потоке пользовательского интерфейса - или, для более разумного, проще управлять опытом, используйте BackgroundWorker.

Может быть и совсем другая проблема; Я не могу точно сказать, что вы написали. Но я уверен, что это большая часть вашей проблемы.

Редактировать

Боже, может быть, мне следует прочитать весь ваш вопрос, а не только его фрагменты, которые первоначально привлекли мое внимание.

Хорошо, я не знаю, насколько жизнеспособным будет этот подход в вашей ситуации, но: BackgroundWorker может вызывать события при выполнении своей задачи; если вы позвоните ReportProgress, это вызовет событие ProgressChanged. Событие ProgressChanged выполняется в потоке пользовательского интерфейса, и я считаю, что метод DoWork блокирует и ожидает завершения обработки обработчиков событий.

Что немного странно в вашей ситуации, так это то, что фоновый процесс ничего не делает. Ваш DoWork метод будет просто продолжать вызывать ReportProgress до тех пор, пока это не будет сделано.

Еще один способ сделать это - использовать таймер. Поместите изображения, которые вы хотите обновить, в очередь (или объекты, которые загружают изображения) в очередь, и установите таймер так, чтобы его обработчик событий Tick обрабатывал первый элемент в очереди. Обработчик событий остановит таймер, обработает текущий рабочий элемент, а затем снова запустит таймер с интервалом в одну десятую секунды. Конечным результатом будет то, что после обработки каждого изображения пользовательский интерфейс будет иметь десятую долю секунды для обработки любых ожидающих событий пользовательского интерфейса - например, рисование изображения на экране.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...