Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy a FrameworkElement including the overflowed content?

I'm using some code that I found at http://brianlagunas.com/wpf-copy-uielement-as-image-to-clipboard/ to copy a rendered XAML Treeview. The treeview is configured for scrolling if the content overflows the available height.

const long DPI = 96;
FrameworkElement element = (FrameworkElement)param;
double height = element.ActualHeight;
double width = element.ActualWidth;
RenderTargetBitmap bmp = new RenderTargetBitmap((int)Math.Round(width), (int)Math.Round(height), DPI, DPI, PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
    VisualBrush vb = new VisualBrush(element);
    dc.DrawRectangle(vb, null, new Rect(new Point(), new Size(width, height)));
}
bmp.Render(dv);

DataObject _data = new DataObject();
_data.SetImage(bmp);

That works fine when my content fits inside the client area:

Treeview when client area is large enough to avoid overflow

But it's problematic when the content overflows the client area:

Treeview when client area is too small and overflow occurs

Is there a way that I can get the entire control content without having to resize the onscreen element?

Edit: Here's the Treeview XAML:

    <TreeView x:Name="ProjectTree" Grid.Row="1"
              ItemContainerStyle="{StaticResource ShinyTreeView}"
              HorizontalContentAlignment="Stretch"
              MouseDoubleClick="TreeView_OnMouseDoubleClick"
              Style="{StaticResource CodeExplorerTreeViewStyle}" BorderThickness="0,1"
              VirtualizingPanel.IsVirtualizing="False">
        <i:Interaction.Behaviors>
            <controls:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
        </i:Interaction.Behaviors>
    </TreeView>

And the button that binds the treeview to the button's command:

            <Button Command="{Binding CopyResultsCommand}" CommandParameter="{Binding ElementName=ProjectTree}">
                <Image Height="16" Source="../../Resources/document-copy.png" />
                <Button.ToolTip>
                    <TextBlock Text="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeExplorer_CopyToolTip}" />
                </Button.ToolTip>
            </Button>
like image 380
ThunderFrame Avatar asked Jun 01 '16 15:06

ThunderFrame


1 Answers

I did some experimentation with your code. The problem appears to be that you're using element.ActualHeight and element.ActualWidth to construct the bitmap, which of course is equal to the current size of the TreeView control (not the content panel which is actually longer), so that's what you get rendered in the output.

What I did to fix the problem was to set ScrollViewer.VerticalScrollBarVisibility to Disabled for the TreeView and then wrap it inside a ScrollViewer. This will make your TreeView full-height that it requires and still having a scrollbar to scroll through it. Now when you construct your bitmap using ActualWidth and ActualHeight, you get a full-size bitmap and rendering it gives the desired result.

like image 195
dotNET Avatar answered Sep 28 '22 00:09

dotNET