우리는 다소 큰 WPF 비즈니스 응용 프로그램이 있으며 기존 WPF FixedPage/FixedDocument 보고서의 다시 작업하고 있습니다.UIElement.UpdateLayout을 사용해야하는 이유는 무엇입니까?
다소 바쁜 생태계입니다. 우리는 당신이 입을 수있는 많은 다른 컨트롤을 가진 폼 생성기를 내장하고 있습니다 (미니 빌트인 비주얼 스튜디오처럼 생각하십시오). 모두 잘 작동합니다. 화면에서 양식을 채운 다음 동일한 사본을 표준 8.5x11 용지에 인쇄 할 수 있습니다 (XPS로).
코드에서이 보고서를 수직 청크로 구분합니다. 각 덩어리가 인쇄 된 종이 위에 1 인치 또는 2 개의 키가 될 것이라고 가정 해보십시오. 이것이 우리가 페이지 매김을 처리하는 방법입니다. 다음 청크가 페이지에 비해 너무 크면 NewPage()를 반복합니다. 내가 언급했듯이, 이것은 잘 작동했다.
WPF는 엄청난 학습 곡선을 가지고 있으며 코드의 크기를 줄이기 위해 이전 코드와 리팩터링을 거쳐 DataTemplates, 강력한 형식의 ViewModels 및 일반 ContentControls를 사용해 행복하게 작업했습니다. 화면상의 양식 생성기는 여전히 작동하지만 FixedDocument 보고서가 이상하게 보입니다.
이러한 세로 조각으로 돌아가서 우리는 사용자의 양식을 개별 그리드 컨트롤로 종이에 인쇄합니다. 멋진 일은 없어. 각 그리드 (위에서 언급했듯이)는 체크 박스, 라디오 버튼, 텍스트 블록 등 임의의 혼합을 포함하는 1 ~ 2 개의 고배율을 가질 수 있습니다. 때때로, 지금 즉, 100 × 67
을
System.Windows.Controls.Grid g = .....
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
를 적절한 크기를 다시 얻을 : 그리드는 이러한 재고 (표준) MS WPF 컨트롤을 포함하면
, 나는 하루 종일이 작업을 수행 할 수 그리드는 하나 개의 제어 할 수 있습니다 - 헤더를 사용하면 (예 : "이 달의 일정) 유일한 자식 컨트롤은 ContentControl을이다
ContentControl에 단순히 뷰 모델에 바인딩되는 그리드에 추가 할 경우 :
..리소스 딕셔너리에이 바인딩을 선택하는 두 개의 DataTemplates가 있습니다. 여기에 그 내용을 보여 드리겠습니다.
<UserControl.Resources>
<w:MarginConverter x:Key="boilerMargin" />
<DataTemplate DataType="{x:Type render:BoilerViewModel}">
<render:RtfViewer
Width="{Binding Path=Width}"
TextRTF="{Binding Path=Rtf}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type render:Qst2NodeViewModel}">
<ContentControl Content="{Binding Path=BoilerVm}">
<ContentControl.Margin>
<MultiBinding Converter="{StaticResource boilerMargin}">
<Binding Path="NodeCaptionVm.Height" />
<Binding Path="NodeLeft" />
</MultiBinding>
</ContentControl.Margin>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
ContentControl은 맨 아래의 데이터 형식을 선택합니다. 그런 다음 템플릿은 위의 작은 템플릿을 사용합니다.
공상 변환기는 단지 여백을 설정합니다. 읽기가 어려울 수 있지만이 모든 내용은 상위 usercontrol 내의 화면에 올바르게 표시됩니다. 그것은 모든 적절한 크기와 칭의와 모든 것입니다.
인쇄 된 보고서 측면 (XPS)에서 코드에서 이러한 컨트롤을 만들고 현재 FixedPage에 맞는지 확인해야합니다. 이 단계를 수행 할 때 : (이 ContentControl을 포함하는 격자에서)
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
다시 0,0 크기가됩니다. 예를 들어 730x27과 같아야합니다. 다시, 화면에서, UserControl에서 호스팅,이 모든 작동합니다. 코드를 인스턴스화하고 순수하게 코드로 측정하려고하면 오류가 발생합니다. 나는 컨트롤이 그리드에 추가되고 행과 열 집합이 Children 컬렉션 등에 추가되었음을 확인했다.나는에 UpdateLayout 비싼 것을 읽어 봤는데 피해야 할
g.UpdateLayout(); //this fixes it
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
, 나는 차라리 : 내가 에 UpdateLayout 호출로 두 문 앞에 추가하면
,이 같은, 그것은 작동 FixedDocument 보고서의 내 FixedPage에 추가하기 전에 각 그리드 섹션에서 호출하지 마십시오. 수십 또는 수백 번의 반복이있을 수 있습니다. 그리드에 일반 WPF 컨트롤이 있고 ContentControls가없고 멋진 데이터 형식을 찾고 조회하는 경우에도 UpdateLayout 호출 없이도 제대로 작동합니다.
어떤 조언이 필요합니까? 고맙습니다!
Xaml 엔진을 사용하기 시작한 이유를 이해해야 만하는 이유를 알 수 없습니다. 내가 고급 기능을 사용하여 처벌받는 것처럼 느껴집니다.
여기 뭔가있는 것 같아요. 측정 코드를 무시하고 그리드를 내 보고서 (FixedDocument의 현재 FixedPage)에 추가하면 매우 흥미로운 일이 발생합니다. 먼저 그리드가 Measured, Arranged입니다. 나는 이것을 밟았다. arrangeBounds가 0,0으로 오르는 것과 같은 문제가 있습니다. 그런 다음 몇 가지 이유로 다시 돌아와 측정을 반복합니다. 두 번째로, 그리드의 실제/실제 크기가 나타납니다. 나는 왜 그것이 반복되고 있는지 알았 으면 좋겠다. 그건 내가 뭘 놓치고 있는지 더 잘 이해할 수있다. –
나에게 말하기가 어렵다. 코드가 잘 모르겠지만, 어떻게 움직이는 지 알 수있다. :) –
두 번째 단계에서 호출 스택의 "외부 코드"를 보았습니다. 두 번째 단계는 실제로 컨트롤의 정확한 크기를 가져 오는 것입니다. WPF 엔진이 UpdateLayout을 호출하여이를 수행하고 있음을 알았습니다. 첫 번째 과거에, 그렇지 않은 경우. 매우 흥미로운.글쎄, 적어도 내 측정을하는 방법을 알고, 나는 아직도 거기에 템플릿이나 ContentControls되지 않습니다 거기에 정상적인 컨트롤이 처음으로 작동하는지 이해하고 싶습니다. 아마 당신이 말하는 이유 때문일 겁니다. 더 많은 것을 찾으면 업데이트 할 것입니다. 다시 한 번 감사드립니다 –