2013-02-22 2 views
0

인쇄물을 제공하려는 WPF 데이터 입력 화면/창이 있습니다. (정확히 말해서, 나는 인쇄하고 싶은 TabControl에서 TabItem처럼 작동하도록 조작 한 UserControl이다.)WPF에서 인쇄

멋지게 인쇄하려면 두 개의 레이아웃 변환을 만들고, 창 크기를 용지 크기를 변경하고 응용 프로그램의 스킨을 변경합니다. '인쇄 스킨'은 배경을 흰색으로 변경하고 머리글 라벨 등의 배경을 제거합니다.

이것은 완벽하게 작동했습니다. 어떤 일이 일어 났는지 묻는 메시지는 MessageBox.Show()입니다.

그러나 Messagebox.Show 프롬프트를 열어 보니 모든 인쇄 매직이 작동하지 않는 것으로 나타났습니다. 인쇄 방법이 Enire 인 경우는 마치 UserControl의 PrintVisual();입니다. (나는 깨는 일없이 제거 할 수없는 하나의 메시지 박스까지이 좁혀.)

코드 (미안 그것은, 내가 대량 의견을 너무 오래 추가 한 것) :

private void PrintStatements() 
{ 
    PrintDialog print = new PrintDialog(); 

    /// Needed data 
    PrintCapabilities capabilities = print.PrintQueue.GetPrintCapabilities(print.PrintTicket); 
    double pageMargin = 1/2.54; // 1cm 
    double pageWidth = capabilities.PageImageableArea.ExtentWidth - (pageMargin); 
    double pageLength = capabilities.PageImageableArea.ExtentHeight - (pageMargin); 
    Size pageSize = new Size(pageWidth, pageLength); 
    ResourceDictionary resources = new ResourceDictionary(); 

    bool canPrint = print.ShowDialog() ?? false; 
    if (canPrint) 
    { 
    double tabWidth = StatementsTabCtrl.ActualWidth; 
    double tabHeight = StatementsTabCtrl.ActualHeight; 

    /// 1. Get tab item content ('currentTabContent') 
    StatementsTabItem currentTabContent = StatementsTabCtrl.SelectedContent as StatementsTabItem; 

    /// 2. Get Original Specs of currentTabContent 
    ResourceDictionary origSkin = Application.Current.Resources; 
    Size origSize = new Size(currentTabContent.ActualWidth, currentTabContent.ActualHeight); 
    Transform origTransform = currentTabContent.LayoutTransform; 

    /// 3. Transform currentTabContent (expose print panels, move stuff around etc) - 
     //do this inside TabItem class 
    currentTabContent.SetupPrinting(); 

    /// 4. Make changes outside TabItem (skin, page-scale) 
     // skin 
    resources.MergedDictionaries.Add(Application.LoadComponent(new Uri(@"Skin/PrintDictionary.xaml", UriKind.Relative)) as ResourceDictionary); 
    Application.Current.Resources = resources; 
     // page-scale 
    double scale = Math.Min(pageWidth/currentTabContent.ActualWidth, 
          pageLength/currentTabContent.ActualHeight); 

    // ****Uncomment next line - printing magic works.**** // 
    // MessageBox.Show(string.Format("scaling by {0}", scale)); 
    System.Threading.Thread.Sleep(250); 

    currentTabContent.LayoutTransform = new ScaleTransform(scale, scale); 

    //Measure and Arrange 
    currentTabContent.Measure(pageSize); 
    ((UIElement)currentTabContent).Arrange(new Rect(
     new Point((capabilities.PageImageableArea.OriginWidth + pageMargin), 
      (capabilities.PageImageableArea.OriginHeight + pageMargin)), pageSize)); 

    System.Threading.Thread.Sleep(250); 

    /// 5. Print (Finally!) 
    print.PrintVisual(currentTabContent, "Print Results"); 

    /// 6. Return everything to normal (undo 3, then 4) 
     // undo 3. 
    currentTabContent.TearDownPrinting(); 
     // undo 4. 
    Application.Current.Resources = origSkin; 
    scale = Math.Max(currentTabContent.ActualWidth/pageWidth, 
            currentTabContent.ActualHeight/pageLength); 
    currentTabContent.LayoutTransform = new ScaleTransform(1/scale, 1/scale); 

    currentTabContent.Measure(origSize); 
    ((UIElement)currentTabContent).Arrange(new Rect(0, 0, tabWidth, tabHeight)); 
    } 
} 

보시다시피, 나는 변경 사항을 인식하는 데 더 많은 시간이 필요할 경우에 대비하여 두 가지를 추가하려고 시도했지만 효과가 없습니다. PrintDialog() 전화와 관련된 이상한 점도 마찬가지입니다. 일반적인 방법으로 호출하면 아무런 효과가 없습니다.

아무에게도 내 인쇄 기능이 MessageBox 호출없이 작동하지 않는 이유를 알 수 있습니까, 아니면 MessageBox 호출을 시뮬레이트하여 프로그램을 작동시키는 방법을 말해 줄 수 있습니까? 누락 수 많은, 많은 TIA

+0

상황을 재현하기가 쉽지 않습니다. xaml 코드와 PrintStatement 메서드가 호출 된 부분을 추가하십시오. 어쩌면 이것은 이것을 재현하는 데 도움이 될 것입니다. – rhe1980

+0

아마도 currentTabContent.Refresh()를 호출하면됩니다. Thread.Sleep (250)은 측정 및 배열을 수행하는 스레드를 호출 할 때 도움이되지 않습니다. 어쨌든 나는 인쇄용으로 currentTabContent 사본을 사용하고 (예 : VisualBrush) 원본 앞으로 및 뒤로 조작 할 것입니다. – LPL

+0

@ rhe1980 주말 내내 일을 그만 두었습니다. xaml과 전화 코드를 추가합니다 월요일 – mcalex

답변

0

부분은 MessageBox.Show();가 UIElement에 너무

이 적어도 작동

ui.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));// activates ui.InvalidateMeasure(); 
    ui.Arrange(new Rect(new Point(0, 0), ui.DesiredSize));     // activates ui.InvalidateArrange(); 

    ui.UpdateLayout(); // <-- refreshed your UIElement 

다음 코드를 사용하여 수동으로 UIElement에를 refesh 경우가 충분해야 새로 고쳐이다 내 경우에

사이드 노트 :
변경하거나 배열하지 않기 때문에 ui.Invalidate...을 직접 호출해서는 안됩니다. se UpdateLayout() 귀하의 웹 사이트를 새로 고치지 않았습니다 UIElement AFAIK