2012-06-14 3 views
1

У меня простая проблема, но решение кажется сложным. Я хочу распечатать, используя холст управления WPF во время цикла; но для каждой итерации я хочу обмануть элемент управления холстом.WPF - печать во время цикла

Если я хочу, чтобы напечатать управление холст в WPF, я могу просто позвонить

PrintDialog dialog = new PrintDialog(); 
dialog.PrintVisual(this.canvas, ""); 

И он печатает, как ожидается, на мой принтер по умолчанию. Замечательно.

Однако, если я хочу выполнить это несколько раз в цикле и сделать обновление для холста во время каждой итерации, будет напечатана только окончательная итерация цикла.

private void methodName() 
    { 
     for (int i = 0; i < 2; i++) 
     { 
      updateTextBox(i.ToString()); 
      PrintDialog dialog = new PrintDialog(); 
      dialog.PrintVisual(this.canvas, ""); 
     } 
    } 

    private void updateTextBox(string text) 
    { 
     txtTextBox.Text = text; 
    } 

Любая идея, что мне нужно сделать, чтобы убедиться, что я получаю 2 распечатки, то первое со значением txtTextBox.Text от 0, во второй раз он имеет значение 1?

+0

Является ли 'PrintVisual' асинхронной функцией? MSDN не упоминает об этом. – Vlad

+0

http://msdn.microsoft.com/en-us/library/system.windows.controls.printdialog.printvisual.aspx Печать - последняя команда, которая должна быть выполнена, поэтому она только «подбирает» последнюю итерацию это последнее, что нужно выполнить. Это нежелательно для моего приложения. Я попытался сыграть с классом DispatcherOperation, чтобы изменить приоритет, но это не помогло. – Dave

+0

Ну, я не вижу информацию об асинхронном поведении в документации. Вы уверены, что это не ошибка? – Vlad

ответ

1

OK

Я решил.

Я удалил все методы объекта диспетчера, чтобы он работал на одном потоке.

Чтобы обновить холст, я использовал метод canvas.UpdateLayout().

Я также удостоверился, что печать была закончена, прежде чем обновлять следующий холст (следующая итерация).

private void methodName() 
{ 
    for (int i = 0; i < 2; i++) 
    { 
     updateTextBox(i.ToString()); 

     this.canvas.UpdateLayout(); 

     PrintDialog dialog = new PrintDialog(); 
     dialog.PrintVisual(this.canvas, "ABC"); 

     dialog.PrintQueue.Refresh(); 

     while (dialog.PrintQueue.NumberOfJobs != 0) 
     { 
      bool isQueued = false; 
      foreach (var job in dialog.PrintQueue.GetPrintJobInfoCollection()) 
      { 
       if (job.Name == "ABC") 
        isQueued = true; 
      } 

      if (!isQueued) 
       break; 

      Thread.Sleep(500); 
      dialog.PrintQueue.Refresh(); 
     } 
    } 
} 

private void updateTextBox(string text) 
{ 
    txtTextBox.Text = text; 
} 

я мог бы просто сделать Thread.Sleep (3000) - это работает, как это было достаточно времени, чтобы обеспечить работу на печать была завершена, но это было также немного «надежды», и я хотел что-то еще безопасный.

Благодарим всех за ваши предложения.

0

Если вы собираетесь вызывать PrintVisual несколько раз, вам нужно изучить PrintDocument и DocumentPaginator.

+0

... и что не так с кодом OP? – Vlad

+0

Я не думал, что смогу использовать PrintVisual и PrintDocument вместе ... Вы имели в виду, что мне нужно использовать PrintDocument вместо этого (извините, если этот вопрос придирчив, но я чувствую, что я не в своей глубине) – Dave

+0

Я могу сделать и у нас есть несколько предложений на странице - будь то аккуратное элегантное решение, я думаю, что это зависит от программиста, но если это сработает, то это сработает! – Dave

0

Просто предположим, но, возможно, стоит попробовать RenderTargetBitmap, чтобы заставить рендеринг холста на каждой итерации, а затем создать изображение с этим источником, которое затем можно отправить в PrintVisual. Смотрите этот пост, например код:

Printing viewport

0

Просто, принимая выстрел здесь, но вы можете попробовать освежающие элементы управления WPF холст в начале каждой итерации цикла для? Вот фрагмент кода:

// declare this 
public static class ExtensionMethods 
{ 
    private static Action EmptyDelegate = delegate() { }; 

    public static void Refresh(this UIElement uiElement) 
    { 
     uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); 
    } 
} 

// the loop 
for (int i = 0; i < 2; i++) 
    { 
     updateTextBox(i.ToString()); 
     PrintDialog dialog = new PrintDialog(); 
     dialog.PrintVisual(this.canvas, ""); 
    } 
} 

// update this method 
private void updateTextBox(string text) 
{ 
    txtTextBox.Text = text; 
    txtTextBox.Refresh(); 
    Thread.Sleep(500); 
} 

Я поиск этой идеи из here

+0

Привет, нет, это не помогло - я действительно пробовал simialr - см. Мой оригинальный вопрос (который, кажется, не получил ответа) - http://stackoverflow.com/questions/10902791/c-sharp-printing-with-wpf Thank вы за свою помощь. – Dave

1

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

for (int i = 0; i < 2; i++) 
{ 
    updateTextBox(i.ToString()); 
    this.canvas.InvalidateVisual(); // Maybe not needed in your case 

    PrintDialog dialog = new PrintDialog(); 

    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (Action)delegate() 
    { 
    dialog.PrintVisual(this.canvas, "" + i); 
    }); 
} 

Да, это несколько напоминает (но не идентичны) ответ SalGad и пост вы имеете в виду, но я не могу прокомментировать этот ответ, поэтому, пожалуйста, попробуйте это, это работает для меня.

У меня также были проблемы с исчезающими отпечатками при использовании пустого описания для заданий на печать, таким образом, + i. Не знаю, является ли это общей проблемой или просто что-то с настройкой моего принтера.

У меня возникла идея от this post, в которой также упоминается альтернативное решение с использованием ViewBox.

+0

Я сделал что-то, что исправляет его, но я думаю, что ваш ответ может быть более изящным. Я проверю это, когда закончу работу сегодня - я все равно опубликую свой ответ, поскольку меня интересуют другие. Я действительно не могу поблагодарить вас за вашу помощь. – Dave

Смежные вопросы