2016-04-20 5 views
0

Я хочу сделать снимок моего UserControl, который еще не был показан. Вот мой код:Создайте снимок неотображенного 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», когда я начинаю App. «MyViewModel» содержит список «SubViews», которые являются содержимым вкладок, и они содержат «FunctionKeyBar», кнопки которых можно активировать с помощью «F1» - «F12». Но после создания снимка экрана я больше не могу использовать F1-F12. Также есть другие проблемы, такие как язык переключения. Есть ли другой способ создания моментального снимка элемента управления, который не появился в поле зрения?

Спасибо за все ответы.

Привет Бенни

ответ

0

подход: Набор Margin к отрицательным, чтобы сохранить его скрытый, добавить элемент управления в сетке/любой другой контейнер.

enter image description here

Выполните следующие действия:

1) Создать Task создать и добавить свой ContentControl в Grid.

2) Call user-define CaptureScreen() функция.

3) Visibility не должен быть скрыт/скомпенсирован. 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; 
} 
+0

Hello AnjumSKhan, спасибо за быстрый ответ. Моя проблема в том, что я хочу показать пользователю предварительный просмотр, поэтому я не могу поместить _ContentControl в визуальное дерево, прежде чем делать снимок. – Benny

+0

@Benny plz см. Обновленный ответ, работает как шарм. – AnjumSKhan

+0

Я пробовал это сейчас, но это не решение для моей проблемы. Я должен использовать .NET 4.0, который имеет некоторые различия в шаблоне async-wait. Другое дело, у меня есть до 5 экземпляров (что зависит от конфигурации) «MyViewModel», из которых я хочу сделать снимок экрана (или миниатюру) после загрузки моего приложения. Я пробовал ваше решение в тестовом проекте, и это довольно хорошо, но в моем случае это вызывает много рендеринга, что замедляет мою работу. – Benny

0

Теперь я нашел решение, благодаря AnjumSKan. Я взял его код и немного изменил его. Как я уже сказал, мне нужно создать снимок при запуске приложения или изменении культуры, и у меня есть несколько видов. в моей функции AddContentControl, я добавляю Контент в мой TabControl, у которого есть отрицательная маржа. Добавить конец, который я вызываю HiddenTab.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new Action(CreateSnapshotOnRender));

('HiddenTab' - мой TabControl, который не показан пользователю). Это вызывает функцию, называемую CreateSnapshotOnRender, где я вызываю метод AnjumSKhan's 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, потому что вы привели меня к этому. Вот почему я обозначил ваш ответ как правильный.

Смежные вопросы