2016-04-20 13 views
0

Ich möchte einen Snapshot von meinem UserControl machen, der noch nicht gezeigt wurde. Das ist mein Code:Erstelle Snapshot eines nicht gezeigten UserControls

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

Dieser Code wird für jede 'MyViewModel', wenn ich meine App starten. 'MyViewModel' enthält eine Liste von 'SubViews', die den Inhalt der Tabs darstellen und eine 'FunctionKeyBar' enthalten, deren Buttons mit 'F1' bis 'F12' aktiviert werden können. Aber nachdem ich meinen Screenshot erstellt habe, kann ich die F1 bis F12 nicht mehr verwenden. Auch gibt es andere Probleme, wie Switch-Sprache. Gibt es eine andere Möglichkeit, einen Snapshot eines Steuerelements zu erstellen, das nicht angezeigt wurde?

Vielen Dank für alle Antworten.

Grüße Benny

Antwort

0

Ansatz: Margin auf negativ setzte es versteckt zu halten, um die Steuerung zu der Tabelle/jeden anderen Behälter hinzufügen. Erstellen

1) eine Task erstellen und fügen Sie Ihre ContentControl zum Grid:

enter image description here

folgenden Schritte aus.

2) Benutzerdefiniert CaptureScreen() Funktion aufrufen.

3) Visibility darf nicht verdeckt/kollabiert sein. Margin kann negativ sein, um das Steuerelement zu verbergen.

In diesem Beispiel habe ich dies in einem Button.Click getan.

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

Hallo AnjumSKhan, danke für schnelle Antwort. Mein Problem ist, ich möchte dem Benutzer eine Vorschau zeigen, so dass ich das _ContentControl nicht in den visuellen Baum einfügen kann, bevor ich den Snapshot mache. – Benny

+0

@Benny PLZ siehe aktualisierte Antwort, funktioniert wie ein Charme. – AnjumSKhan

+0

Ich habe das jetzt versucht, aber es ist nicht wirklich eine Lösung für mein Problem. Ich muss .NET 4.0 verwenden, was einige Unterschiede im async-await-Muster hat. Die andere Sache ist, ich habe bis zu 5 Instanzen (was von der Konfiguration abhängt) von 'MyViewModel', von dem ich nach dem Laden meiner Anwendung einen Screenshot (oder Thumbnail) machen möchte. Ich habe versucht, Ihre Lösung in einem Testprojekt und es ist ziemlich nett, aber in meinem Fall verursacht es eine Menge Rendering, was meine Leistung verlangsamt. – Benny

0

Jetzt habe ich eine Lösung gefunden, dank AnjumSKan. Ich nahm seinen Code und änderte es ein wenig. Wie gesagt, ich muss den Snapshot beim Start der Anwendung oder Kultur geändert haben und ich habe mehr als eine Ansicht. In meiner Funktion AddContentControl füge ich den Inhalt zu meinem TabControl hinzu, das einen negativen Rand hat. Fügen Sie das Ende ich rufe HiddenTab.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new Action(CreateSnapshotOnRender));

('HiddenTab' ist meine TabControl, die nicht für den Benutzer angezeigt wird). Dies ruft eine Funktion namens CreateSnapshotOnRender auf, wo ich AnjumSKhans CaptureScreen -Methode ausrufe. Danach rufe ich wieder die Funktion AddContentControl mit meinem nächsten Inhalt auf. Das sieht wie folgt aus:

Danke nochmal an AnjumSKan, weil du mich dazu geführt hast. Deshalb habe ich Ihre Antwort als die richtige markiert.