我需要使用XAML生成一个打印的表单,该表单包含一个表头网格和可变数量的行,随着行数的增加可能导致出现多个页面。标题必须出现在每个页面上,并且每行的高度可能因行内的文本换行而有所不同。我目前正在尝试使用ActualHeight的ItemsControl(行容器)来确定何时生成新页面,但ActualHeight的值始终为零。使用ItemsControl ActualHeight分页打印的XAML表单?
我的“XAML_Form”具有以下结构。 ItemTemplate中使用一个网格,允许将行中的列与标题网格中的列对齐。
<Grid Width="980" Height="757">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Name="_headerControl" Grid.Row="0"/>
<ItemsControl Name=_rowsControl ItemsSource={Binding Rows} Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
我们的架构有一个报告类,用于处理添加页脚,页码以及将页面聚合到PDF中。此报告类为每个XAML View页面都有一个嵌套的ViewModel。该视图模型的每一页使用行对象的后备名单:
List<RowClass> RowsList;
视图模型还具有用于绑定的ItemsSource时的ICollectionView:
ICollectionView Rows = new ListCollectionView(RowsList);
我的报告类有一个CreatePages方法,包含这样的代码:
IList<XAML_Form> pages = new List<XAML_Form>();
var vm = new PageViewModelClass();
var page = new XAML_Form { DataContext = vm };
page.InitializeComponent();
page.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity);
page.Arrange(new Rect(new Point(0,0), page.DesiredSize));
var maxRowsHeight = page.DesiredSize.Height - page._headerControl.ActualHeight;
pages.Add(page);
var rowsOnPage = 0;
foreach (var row in sourceRowsObjectList)
{
rowsOnPage++;
vm.RowsList.Add(row);
vm.Rows.Refresh();
page.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity);
page.Arrange(new Rect(new Point(0,0), page.DesiredSize));
if (page._rowsControl.ActualHeight <= maxRowsHeight)
continue;
// The rows exceed the available space; the row needs to go on the next page.
vm.RowsList.RemoveAt(--rowsOnPage);
vm = new PageViewModelClass();
vm.RowsList.Add(row);
rowsOnPage = 1;
page = new XAML_Form { DataContext = vm };
page.InitializeComponent();
pages.Add(page);
}
return pages;
初始测量/安排并为我提供MAXR的预期值owsHeight。生成的表单对于有几行的单个页面看起来很好。我的具体问题是:为什么page._rowsControl.ActualHeight总是为零?一般来说,是否有更好的方法来解决这个问题?
我是通过WPF博士的一系列更深的挖掘到的ItemsControl。我发现“网格”不是项目控制类的主机项目之一。这与这有什么关系? –
终于在这方面取得了一点进展。可以调用“非常气馁的”UpdateLayout方法。由于这是非常昂贵的,我不想在添加每一行后调用UpdateLayout。相反,我将添加应该放在页面上的行数,而不包装,然后调用UpdateLayout。如果它们不合适,则继续删除一行并调用UpdateLayout,直到行适合。仍然不喜欢这种方法,但它看起来会起作用。 –