从项目控件中获取 ItemsPanel
Get ItemsPanel from Items Control
所以我正在构建一个 WPF 拖放设计器。
一旦用户完成设计,我希望他们能够打印他们拥有的东西。
这一直有效,直到我决定 canvas 上的所有项目实际上都应该数据绑定到视图模型。为此,我将 canvas 包装在一个项目控件中。我 运行 现在遇到的问题是我构建的打印功能无法访问 canvas 来打印它。我愿意接受建议。
<ItemsControl x:Name="CanvasItemsControl" Grid.Column="1" Width="600" Height="800" ItemsSource="{Binding CanvasElements}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Grid.Column="1" AllowDrop="True" Width="600" Height="800"
x:Name="CanvasControl"
Background="White"
DragEnter="CanvasFlowDocument_DragEnter"
DragLeave="CanvasFlowDocument_DragLeave"
DragOver="CanvasFlowDocument_DragOver"
Drop="CanvasFlowDocument_Drop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:CanvasElement />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
C#
private void PrintCanvas()
{
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == true)
{
/*
NEED TO ACCESS CANVAS CONTROL HERE TO PRINT
I KNOW THE BELOW PRINT METHOD WORKS.
IT WORKED UNTIL I ADDED THE ITEMS CONTROL WRAPPER AROUND THE CANVAS
*/
//get the size of the printer page
PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);
double pageMargin = Math.Min(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight);
double additionalMargin = Math.Max(0, 20 - pageMargin);
Size pageSize = new Size(capabilities.PageImageableArea.ExtentWidth - additionalMargin * 2, capabilities.PageImageableArea.ExtentHeight - additionalMargin * 2);
//get scale of the print wrt to screen of WPF visual
double scale = Math.Min(pageSize.Width / CanvasControl.ActualWidth, pageSize.Height / CanvasControl.ActualHeight);
Size printSize = new Size(CanvasControl.ActualWidth * scale, CanvasControl.ActualHeight * scale);
Point upperLeft = new Point(capabilities.PageImageableArea.OriginWidth + additionalMargin, capabilities.PageImageableArea.OriginHeight + additionalMargin);
//Transform the Visual to scale
CanvasControl.LayoutTransform = new ScaleTransform(scale, scale);
CanvasControl.Measure(printSize);
CanvasControl.Arrange(new Rect(upperLeft, printSize));
FlowDocument CanvasFlowDocument = new FlowDocument();
BlockUIContainer buiCont = new BlockUIContainer();
CanvasControl.Drop -= CanvasFlowDocument_Drop;
CanvasControl.DragOver -= CanvasFlowDocument_DragOver;
CanvasControl.DragLeave -= CanvasFlowDocument_DragLeave;
CanvasControl.DragLeave -= CanvasFlowDocument_DragEnter;
Grid parent = (Grid)CanvasControl.Parent;
parent.Children.Remove(CanvasControl);
buiCont.Child = CanvasControl;
CanvasFlowDocument.Blocks.Add(buiCont);
pd.PrintDocument((CanvasFlowDocument as IDocumentPaginatorSource).DocumentPaginator, "Template");
CanvasFlowDocument.Blocks.Clear();
buiCont.Child = null;
ReloadUI(parent);
}
}
您应该可以使用 PrintDialog.PrintVisual(Visual,string) to print out your control directly. You may need to play with size though, but the code you have to do the resizing should work. See this post which is similar and links to this article 作为可能的解决方案。
所以我正在构建一个 WPF 拖放设计器。
一旦用户完成设计,我希望他们能够打印他们拥有的东西。
这一直有效,直到我决定 canvas 上的所有项目实际上都应该数据绑定到视图模型。为此,我将 canvas 包装在一个项目控件中。我 运行 现在遇到的问题是我构建的打印功能无法访问 canvas 来打印它。我愿意接受建议。
<ItemsControl x:Name="CanvasItemsControl" Grid.Column="1" Width="600" Height="800" ItemsSource="{Binding CanvasElements}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Grid.Column="1" AllowDrop="True" Width="600" Height="800"
x:Name="CanvasControl"
Background="White"
DragEnter="CanvasFlowDocument_DragEnter"
DragLeave="CanvasFlowDocument_DragLeave"
DragOver="CanvasFlowDocument_DragOver"
Drop="CanvasFlowDocument_Drop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:CanvasElement />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
C#
private void PrintCanvas()
{
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == true)
{
/*
NEED TO ACCESS CANVAS CONTROL HERE TO PRINT
I KNOW THE BELOW PRINT METHOD WORKS.
IT WORKED UNTIL I ADDED THE ITEMS CONTROL WRAPPER AROUND THE CANVAS
*/
//get the size of the printer page
PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);
double pageMargin = Math.Min(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight);
double additionalMargin = Math.Max(0, 20 - pageMargin);
Size pageSize = new Size(capabilities.PageImageableArea.ExtentWidth - additionalMargin * 2, capabilities.PageImageableArea.ExtentHeight - additionalMargin * 2);
//get scale of the print wrt to screen of WPF visual
double scale = Math.Min(pageSize.Width / CanvasControl.ActualWidth, pageSize.Height / CanvasControl.ActualHeight);
Size printSize = new Size(CanvasControl.ActualWidth * scale, CanvasControl.ActualHeight * scale);
Point upperLeft = new Point(capabilities.PageImageableArea.OriginWidth + additionalMargin, capabilities.PageImageableArea.OriginHeight + additionalMargin);
//Transform the Visual to scale
CanvasControl.LayoutTransform = new ScaleTransform(scale, scale);
CanvasControl.Measure(printSize);
CanvasControl.Arrange(new Rect(upperLeft, printSize));
FlowDocument CanvasFlowDocument = new FlowDocument();
BlockUIContainer buiCont = new BlockUIContainer();
CanvasControl.Drop -= CanvasFlowDocument_Drop;
CanvasControl.DragOver -= CanvasFlowDocument_DragOver;
CanvasControl.DragLeave -= CanvasFlowDocument_DragLeave;
CanvasControl.DragLeave -= CanvasFlowDocument_DragEnter;
Grid parent = (Grid)CanvasControl.Parent;
parent.Children.Remove(CanvasControl);
buiCont.Child = CanvasControl;
CanvasFlowDocument.Blocks.Add(buiCont);
pd.PrintDocument((CanvasFlowDocument as IDocumentPaginatorSource).DocumentPaginator, "Template");
CanvasFlowDocument.Blocks.Clear();
buiCont.Child = null;
ReloadUI(parent);
}
}
您应该可以使用 PrintDialog.PrintVisual(Visual,string) to print out your control directly. You may need to play with size though, but the code you have to do the resizing should work. See this post which is similar and links to this article 作为可能的解决方案。