Использование ItemsControl ActualHeight, чтобы нумеровать страницы печатной формы XAML?

Я должен произвести печатную форму, используя XAML, у которого есть сетка заголовка и переменное количество рядов, которые могут привести к многократным страницам как количество увеличений рядов. Заголовок должен появиться на каждой странице, и каждый ряд может измениться по высоте из-за переноса текста в ряду. Я в настоящее время пытаюсь использовать ActualHeight ItemsControl (контейнер рядов), чтобы определить, когда произвести новую страницу, но у ActualHeight всегда есть ценность ноля .

У моего "XAML_Form" есть следующая структура. Сетка используется в ItemTemplate, чтобы позволить выравнивать колонки в рядах с колонками в сетке заголовка.


    
        
            
            
        
        
        
            
                
                    
                
            
        
    

У нашей архитектуры есть класс отчета, который обращается с добавляющими нижними сносками, номерами страниц и соединением страниц в PDF. У этого класса отчета есть вложенный ViewModel для каждого XAML, Просматривают страницу. ViewModel для каждой страницы использует отступающий Список объектов строки:

   List RowsList;

У ViewModel также есть ICollectionView, который используется, чтобы связать как ItemsSource:

   ICollectionView Rows = new ListCollectionView(RowsList);

У моего класса отчета есть метод CreatePages, который содержит код как это:

IList pages = new List();
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;

Начальная буква Имеет размеры/Устраивает , делает , предоставляют мне математическое ожидание для maxRowsHeight. И произведенная форма выглядит хорошо для единственной страницы с несколькими рядами. Моя определенная проблема: , Почему страница. _ rowsControl. ActualHeight всегда ноль ? И обычно, там лучший подход к этой проблеме?

0
nl ja de
Я рыл глубже в ItemsControl через Доктора WPF' s ряд. Я вижу, что "Сетка" не один из хозяев изделия к классам контроля изделия. Это имело бы какое-либо отношение к этому?
добавлено автор Tobias, источник
Наконец делая немного успехов на этом. "Высоко препятствовавший" метод UpdateLayout можно назвать. Так как это настолько дорого, я don' t хотят назвать UpdateLayout после добавления каждого ряда. Вместо этого я добавлю количество рядов, которые ДОЛЖНЫ соответствовать на странице без обертывания, затем назвать UpdateLayout. Если они don' t подгонка, затем продолжите удалять ряд и называть UpdateLayout до подгонки рядов. Все еще не вне себя от радости из-за этого подхода, но похоже, что это будет работать.
добавлено автор Tobias, источник

1 ответы

Вот решение. Мы пытаемся отделить проблемы представления от проблем модели представления, таким образом, есть все еще улучшения, которые будут сделаны.

Метод CreatePages в классе отчета теперь:

private static IEnumerable CreatePages()
{
    IList pages = new List();
    int rowCount = sourceRowsObjectList.Count;
    int remainingRowCount = rowCount;
    do
    {
        var pageVm = new PageViewModelClass();
        var page = new XAML_Form(pageVm);
        pages.Add(page);

        int numberOfRowsToAdd = Math.Min(remainingRowCount, XAML_Form.MaxNumberOfRows);
        pageVm.AddRows(sourceRowsObjectList.Skip(rowCount - remainingRowCount).Take(numberOfRowsToAdd));
        remainingRowCount -= numberOfRowsToAdd;
        while (page.AreRowsOverflowing())
        {
            pageVm.RemoveLastRow();
            remainingRowCount++;
        }
    } while (remainingRowCount > 0);
    return pages;
}

Подходящий код XAML_Form позади следующие:

private static int _maxNumberOfRows = -1;

public XAML_Form(PageViewModelClass viewModel)
{
    InitializeComponent();
    Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    Arrange(new Rect(new Point(0, 0), DesiredSize);
    ViewModel = viewModel;
}

public PageViewModelClass ViewModel
{
    get { return (PageViewModelClass)DataContext; }
    private set { DataContext = value; }
}

public static int MaxNumberOfRows
{
    get    //Compute this only once, the first time it is called.
    {
        if (_maxNumberOfRows < 0) return _maxNumberOfRows;
        var page = new XAML_Form();
        var singleRowCollection = new object[] { null; }
        page._rowsControl.ItemsSource = singleItemCollection;
        page._rowsControl.UpdateLayout();
        var rowHeight = page._rowsControl.ActualHeight;
        _maxNumberOfRows = (int)((page.DesiredSize.Height - page._headerControl.ActualHeight)/rowHeight);
        page._rowsControl.ItemsSource = null;
        return _maxNumberOfRows;
    }
}

// Call this method as rarely as possible. UpdateLayout is EXPENSIVE!
public bool AreRowsOverflowing()
{
    _rowsControl.UpdateLayout();
    return _rowsControl.ActualHeight > DesiredSize.Height - _headerControl.ActualHeight;
}
0
добавлено
Мы с тех пор оптимизировали это далее, чтобы главным образом постараться не называть UpdateLayout. Возможно, I' ll отправили это в какой-то момент.
добавлено автор Tobias, источник
Мы также оптимизировали, это, создавая "фиктивную группу" в коде позади того единственного содержит средства управления текстовым окном, которые могут обернуть. Тогда мы можем назвать UpdateLayout только на этой фиктивной группе, которая никогда не показывается и не является parented к форме, таким образом, это менее дорого.
добавлено автор Tobias, источник