开发者

WYSIWYG but not when printing

I'm using this control Here to be able to host Table that can bind to a list and to generate rows accordingly, that worked really good, however the table just doesn't appear when printing to an XPS or PDF files, it does appear on the FlowDocument but it prints as blank , I tried changing the colors of B开发者_如何学Goackground and Foreground with no success , any suggestions ?


I have just successfully implemented that example (Create Flexible UIs With Flow Documents And Data Binding) and did experience the same problem as you.

The problem was that the DataContext for the BindableRun is not being set correctly. As explained in the article you need to fix-up the context (using the FixupDataContext helper method), set the DataContext for the FrameworkContentElement, and clear the context that you previous 'fixed' up (using the UnFixupDataContext helper method). The order of execution of these statements is critical. Re-read the article again and make sure you understand it; I had to re-read it several times and study the code to truly understand what he was talking about.

I have taken the implementation one step further and added support for data binding other elements in the TableCell. The changes comprises of using an attached property to identify elements that have their DataContext 'fixed' and then expanding the on the helper methods to also work against FrameworkElements in addition the FrameworkContentElements.

HTH,

Edit:

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;
    }

}

Usage

 <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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜