创建未显示的UserControl的快照

时间:2016-04-20 09:18:35

标签: c# wpf snapshot rendertargetbitmap visual-tree

我想拍摄一张尚未显示的UserControl快照。 那是我的代码:

    public Screenshot(MyViewModel viewModel)
    {
        if (viewModel == null)
            return;

        // Create a TabControl, where View is hosted in
        var visualTab = new TabControl();
        visualTab.Width = FrameworkAdjustments.VisualSize.Width;
        visualTab.Height = FrameworkAdjustments.VisualSize.Height;
        visualTab.TabStripPlacement = Dock.Left;

        // Tabs should only be shown, if there are more than one 'SubView'
        Visibility tabVisibility = Visibility.Collapsed;
        if (viewModel.SubViews.Count > 1)
            tabVisibility = Visibility.Visible;
        foreach (var subView in viewModel.SubViews)
        {
            var tab = new TabItem();
            tab.Header = subView.TranslatedId;    // multilanguage header
            tab.Visibility = tabVisibility;
            if (subView.Id == viewModel.ActiveSubView.Id)
            {
                tab.IsSelected = true;
                // Without the following line my UI works, but my TabControl is empty.
                tab.Content = ViewManager.GetViewById(subView.Id);
                // ViewManager.GetViewById(subView.Id); returns a UserControl
            }

            tab.Measure(FrameworkAdjustments.VisualSize);
            tab.Arrange(new Rect(FrameworkAdjustments.VisualSize));
            visualTab.Items.Add(tab);
        }

        _ContentCtrl = new ContentControl() { Width = FrameworkAdjustments.VisualSize.Width, Height = FrameworkAdjustments.VisualSize.Height };
        _ContentCtrl.Content = visualTab;
        _ContentCtrl.Measure(FrameworkAdjustments.VisualSize);
        _ContentCtrl.Arrange(new Rect(FrameworkAdjustments.VisualSize));

        RenderTargetBitmap bmp = new RenderTargetBitmap((int)FrameworkAdjustments.VisualSize.Width, (int)FrameworkAdjustments.VisualSize.Height, 96, 96, PixelFormats.Pbgra32);
        bmp.Render(_ContentCtrl);

        this.ItemBrush = new ImageBrush(bmp);
    }

此代码适用于每个' MyViewModel'当我开始我的应用程序。 ' MyViewModel'包含一个'子视图列表'这些是标签的内容,它们包含一个' FunctionKeyBar'可以使用' F1'来激活哪些按钮?到' F12'。但是在创建我的截图后,我再也不能使用F1到F12了。还有其他问题,如切换语言。 还有另一种方法可以创建一个尚未进入视图的控件快照吗?

感谢所有回复。

问候本尼

2 个答案:

答案 0 :(得分:1)

方法:将Margin设置为负值以使其隐藏,将控件添加到网格/任何其他容器中。

enter image description here

请按照以下步骤操作:

1)创建Task以创建ContentControl并将Grid添加到CaptureScreen ()

2)调用用户定义的Visibility函数。

3)Margin不得隐藏/折叠。 Button.Click可能是否定的,以隐藏控件。

在此示例中,我在async private void Button_Click(object sender, RoutedEventArgs e) { Task<ContentControl> t = AddContentControl(); ContentControl ctrl = await t; RenderTargetBitmap bmp = CaptureScreen(ctrl, 5000, 5000); Img.Source = bmp; } /* Add the ContentControl to the Grid, and keep it hidden using neg. Margin */ private Task<ContentControl> AddContentControl() { Task<ContentControl> task = Task.Factory.StartNew(() => { ContentControl ctrl = null; Dispatcher.Invoke(() => { ctrl = new ContentControl() { Content = "Not shown", Width = 100, Height = 25, Margin = new Thickness(-8888, 53, 0, 0) }; Grd.Children.Add(ctrl); }); return ctrl; }); return task; } /* Important , wont work with Visibility.Collapse or Hidden */ private static RenderTargetBitmap CaptureScreen(Visual target, double dpiX, double dpiY) { if (target == null) { return null; } Rect bounds = VisualTreeHelper.GetDescendantBounds(target); RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0), (int)(bounds.Height * dpiY / 96.0), dpiX, dpiY, PixelFormats.Pbgra32); DrawingVisual dv = new DrawingVisual(); using (DrawingContext ctx = dv.RenderOpen()) { VisualBrush vb = new VisualBrush(target); ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size)); } rtb.Render(dv); return rtb; }

中完成了此操作
(ex. %userprofile%)

答案 1 :(得分:0)

现在我找到了一个解决方案,感谢AnjumSKan。 我拿了他的代码并稍微改了一下。正如我所说,我需要在应用程序启动或文化更改时创建快照,并且我有多个视图。在我的函数AddContentControl中,我将内容添加到我的TabControl,它具有负边距。添加结束我致电HiddenTab.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new Action(CreateSnapshotOnRender));

('HiddenTab'是我的TabControl,未向用户显示)。这会调用一个名为CreateSnapshotOnRender的函数,我在其中调用AnjumSKhan的CaptureScreen - 方法。之后,我再次使用我的下一个内容调用函数AddContentControl。这看起来如下:

private void CreateScreenshotOnRender()
    {
        HiddenTab.Measure(ViewSize);
        HiddenTab.Arrange(new Rect(ViewSize));
        var snapshot = CaptureScreen(HiddenTab, dpiX, dpiY); 
/* Do anything with snapshot */
        _Index++;      // counter to know thich view is next
        CreateAllScreenshots();
    }

再次感谢AnjumSKan,因为你引导我到这里来。这就是为什么我将你的答案标记为正确答案。