WYSIWYG, но не при печати - PullRequest
       31

WYSIWYG, но не при печати

0 голосов
/ 28 июня 2011

Я использую этот элемент управления Здесь , чтобы иметь возможность размещать таблицу, которая может связываться со списком, и генерировать строки соответственно, что работало действительно хорошо, однако таблица просто не появляется при печати файлы XPS или PDF, они появляются в FlowDocument, но печатаются как пустые, я безуспешно пытался изменить цвета фона и переднего плана, какие-либо предложения?

1 Ответ

0 голосов
/ 28 февраля 2012

Я только что успешно реализовал этот пример ( Создание гибких пользовательских интерфейсов с потоковыми документами и привязкой данных ) и столкнулся с той же проблемой, что и вы.

Проблема заключалась в том, что DataContext для BindableRun установлен неправильно. Как объяснялось в статье, вам нужно исправить контекст (используя вспомогательный метод FixupDataContext), установить DataContext для FrameworkContentElement и очистить контекст, который вы ранее «исправили» (используя UnFixupDataContext вспомогательный метод). Порядок выполнения этих операторов является критическим . Перечитайте статью еще раз и убедитесь, что вы понимаете ее; Мне пришлось несколько раз перечитать его и изучить код, чтобы действительно понять, о чем он говорит.

Я сделал шаг вперед в реализации и добавил поддержку связывания данных с другими элементами в TableCell. Изменения включают использование присоединенного свойства для идентификации элементов, у которых DataContext «исправлено», а затем расширение вспомогательных методов для работы также с FrameworkElements в дополнение к FrameworkContentElements.

HTH,

Редактировать:

public static class DataContextHelper
{

    #region UseAncestorDataContext

    public static readonly DependencyProperty UseAncestorDataContextProperty = DependencyProperty.RegisterAttached("UseAncestorDataContext", typeof(bool), typeof(DataContextHelper),
                                                                                    new FrameworkPropertyMetadata(false, DataContextHelper.OnUseAncestorDataContextChanged));

    public static bool GetUseAncestorDataContext(DependencyObject d)
    {
        return (bool)d.GetValue(UseAncestorDataContextProperty);
    }

    public static void SetUseAncestorDataContext(DependencyObject d, bool value)
    {
        d.SetValue(UseAncestorDataContextProperty, value);
    }

    private static void OnUseAncestorDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
            UseAncestorDataContext(d);
    }

    #endregion

    /// <summary>
    /// If you use a Bindable flow document element more than once, you may encounter a "Collection was modified" 
    /// exception. The error occurs when the binding is updated because of a change to an inherited dependency 
    /// property. The most common scenario is when the inherited DataContext changes. It appears that an inherited 
    /// properly like DataContext is propagated to its descendants. When the enumeration of descendants gets to 
    /// a Bindable, the dependency properties of that element change according to the new DataContext, which change 
    /// the (non-dependency) properties. However, for some reason, changing the flow content invalidates the enumeration 
    /// and raises an exception.
    /// </summary>        
    public static void UseAncestorDataContext(DependencyObject element)
    {            
        if (element is FrameworkContentElement)
        {
            FrameworkContentElement contentElement = (FrameworkContentElement)element;
            Binding binding = new Binding(FrameworkContentElement.DataContextProperty.Name);
            binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1);
            contentElement.SetBinding(FrameworkContentElement.DataContextProperty, binding);
        }
        else if (element is FrameworkElement)
        {
            FrameworkElement frameworkElement = (FrameworkElement)element;
            Binding binding = new Binding(FrameworkElement.DataContextProperty.Name);
            binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1);
            frameworkElement.SetBinding(FrameworkContentElement.DataContextProperty, binding);
        }
    }

    public static void ClearDataContextBinding(DependencyObject d)
    {
        while (RestoreDataContextRecursive(d));            
    }

    private static bool RestoreDataContextRecursive(DependencyObject d)
    {            
        if (d is FrameworkContentElement && GetUseAncestorDataContext(d))
        {
            Binding binding = BindingOperations.GetBinding(d, FrameworkContentElement.DataContextProperty);
            if (binding != null && binding.Path != null && binding.Path.Path == FrameworkContentElement.DataContextProperty.Name
                && binding.RelativeSource != null && binding.RelativeSource.Mode == RelativeSourceMode.FindAncestor && binding.RelativeSource.AncestorType == typeof(FrameworkElement) && binding.RelativeSource.AncestorLevel == 1)
            {
                BindingOperations.ClearBinding(d, FrameworkContentElement.DataContextProperty);
                return true;
            }
        }
        else if (d is FrameworkElement && GetUseAncestorDataContext(d))
        {
            Binding binding = BindingOperations.GetBinding(d, FrameworkElement.DataContextProperty);
            if (binding != null && binding.Path != null && binding.Path.Path == FrameworkElement.DataContextProperty.Name
                && binding.RelativeSource != null && binding.RelativeSource.Mode == RelativeSourceMode.FindAncestor && binding.RelativeSource.AncestorType == typeof(FrameworkElement) && binding.RelativeSource.AncestorLevel == 1)
            {
                BindingOperations.ClearBinding(d, FrameworkElement.DataContextProperty);
                return true;
            }
        }

        // As soon as we have disconnected a binding, return. Don't continue the enumeration, since the collection may have changed
        foreach (object child in LogicalTreeHelper.GetChildren(d))
        {
            if (child is DependencyObject && RestoreDataContextRecursive((DependencyObject)child))
                return true;
        }

        return false;
    }

}

Использование

 <DataTemplate x:Key="PercentCellTemplate">
        <documents:ContentFragment>
            <TableCell Style="{StaticResource TableCellStyle}" BorderThickness="0,0,1,0"> 
                <Paragraph>
                    <Rectangle Width="14" Height="14" VerticalAlignment="Center" Margin="0,6,0,0" Fill="{Binding Path=Result, Mode=OneWay, Converter={StaticResource MappingConverterResultEnumToIconResource}}" 
                               documents:DataContextHelper.UseAncestorDataContext="True"/>
                    <documents:DocumentRun Style="{StaticResource ReportDocument_NormalRunStyle}" Text="{Binding Path=Percent, Mode=OneWay, StringFormat={}{0:0.000}%}" 
                                           BaselineAlignment="Center" documents:DataContextHelper.UseAncestorDataContext="True" />
                </Paragraph>
            </TableCell>
        </documents:ContentFragment>
    </DataTemplate>
...