There really is only one name in XAML, the x:Name
. A framework, such as WPF, can optionally map one of its properties to XAML's x:Name
by using the RuntimeNamePropertyAttribute
on the class that designates one of the classes properties as mapping to the x:Name attribute of XAML.
The reason this was done was to allow for frameworks that already have a concept of "Name" at runtime, such as WPF. In WPF, for example, FrameworkElement
introduces a Name property.
In general, a class does not need to store the name for x:Name
to be useable. All x:Name
means to XAML is generate a field to store the value in the code behind class. What the runtime does with that mapping is framework dependent.
So, why are there two ways to do the same thing? The simple answer is because there are two concepts mapped onto one property. WPF wants the name of an element preserved at runtime (which is usable through Bind, among other things) and XAML needs to know what elements you want to be accessible by fields in the code behind class. WPF ties these two together by marking the Name property as an alias of x:Name.
In the future, XAML will have more uses for x:Name, such as allowing you to set properties by referring to other objects by name, but in 3.5 and prior, it is only used to create fields.
Whether you should use one or the other is really a style question, not a technical one. I will leave that to others for a recommendation.
See also AutomationProperties.Name VS x:Name, AutomationProperties.Name is used by accessibility tools and some testing tools.
I know it's a bit late, but here is the solution I came up with.
First, we create a wrapper that will generate the document pages for us. Each page will have a scale transformation applied to it before returning it.
public class FittedDocumentPaginator : DocumentPaginator
{
public DocumentPaginator Base { get; private set; }
public double Scale { get; private set; }
private readonly ScaleTransform _sTransform;
public FittedDocumentPaginator( DocumentPaginator baseDp, double scale )
{
if ( baseDp == null )
throw new ArgumentNullException( "baseDp" );
Base = baseDp;
Scale = scale;
_sTransform = new ScaleTransform( scale, scale );
}
public override DocumentPage GetPage( int pageNumber )
{
var page = Base.GetPage( pageNumber );
( (ContainerVisual)page.Visual ).Transform = _sTransform;
return page;
}
public override bool IsPageCountValid
{
get { return Base.IsPageCountValid; }
}
public override int PageCount
{
get { return Base.PageCount; }
}
public override Size PageSize
{
get { return Base.PageSize; }
set { Base.PageSize = value; }
}
public override IDocumentPaginatorSource Source
{
get { return Base.Source; }
}
}
Using it is fairly simple:
private void PrintDocument( PrintDialog pd, FlowDocument document, double scale, string title )
{
DocumentPaginator dp = ( (IDocumentPaginatorSource)document ).DocumentPaginator;
FittedDocumentPaginator fdp = new FittedDocumentPaginator( dp, scale );
pd.PrintDocument( fdp, title );
}
If you're interested, here is how we determined the scale. In our case, the document was extended past the page width, but it can easily be modified to accommodate the page height.
private void Print( FlowDocument document, string title, double documentWidth )
{
var pd = new PrintDialog();
if ( pd.ShowDialog() == true )
{
// Set the printing margins.
Thickness pageMargins = document.PagePadding;
document.PagePadding = new Thickness( 15.0 );
// In our case, the document's width is NaN so we have to navigate the visual tree to get the ActualWidth, which is represented by 'documentWidth'.
double scale = documentWidth / pd.PrintableAreaWidth;
if ( scale < 1.0 )
{
// The report fits on the page just fine. Don't scale.
scale = 1.0;
}
double invScale = 1 / scale;
document.PageHeight = pd.PrintableAreaHeight * scale;
document.PageWidth = pd.PrintableAreaWidth * scale;
DocumentPaginator dp = ( (IDocumentPaginatorSource)document ).DocumentPaginator;
FittedDocumentPaginator fdp = new FittedDocumentPaginator( dp, invScale );
pd.PrintDocument( fdp, title );
// Restore the original values so the GUI isn't altered.
document.PageHeight = Double.NaN;
document.PageWidth = Double.NaN;
document.PagePadding = pageMargins;
}
}
Best Answer
If you keep track of the Blocks on the FlowDocument contained in the FlowDocumentReader, than you can simply use:
This works only on the page ViewingModes of the FlowDocumentReader.
if you whould like to do so on the scroll mode, you must go down the visual tree and search for the ScrollViewer, somthing like this: