Question

J'ai trouvé une nouvelle tournure à la question "Visual RenderTargetBitmap"!

Je le rendu des prévisualisations de choses WPF pour un designer. Cela signifie que je dois prendre un visuel et de rendre WPF à un bitmap sans que visuelle jamais affichée. Vous avez une jolie petite méthode pour le faire comme de le voir ici, il va

private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
    Border b = new Border { Width = visual.Width, Height = visual.Height };
    b.BorderBrush = Brushes.Black;
    b.BorderThickness = new Thickness(1);
    b.Background = Brushes.White;
    b.Child = visual;

    b.Measure(new Size(b.Width, b.Height));
    b.Arrange(new Rect(b.DesiredSize));

    RenderTargetBitmap rtb = new RenderTargetBitmap(
                                (int)b.ActualWidth,
                                (int)b.ActualHeight,
                                96,
                                96,
                                PixelFormats.Pbgra32);

    // intermediate step here to ensure any VisualBrushes are rendered properly
    DrawingVisual dv = new DrawingVisual();
    using (var dc = dv.RenderOpen())
    {
        var vb = new VisualBrush(b);
        dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
    }
    rtb.Render(dv);
    return rtb;
}

fonctionne très bien, sauf pour une chose leeetle ... si mon FrameworkElement a une VisualBrush, ce pinceau ne se termine pas dans le bitmap rendu final. Quelque chose comme ceci:

<UserControl.Resources>
    <VisualBrush
        x:Key="LOLgo">
        <VisualBrush.Visual>
            <!-- blah blah -->
<Grid 
    Background="{StaticResource LOLgo}">
<!-- yadda yadda -->

Tout le reste rend au bitmap, mais VisualBrush tout simplement pas montrer. Les solutions Google évidentes ont été tentées et ont échoué. Même ceux qui mentionnent spécifiquement VisualBrushes absents de bitmaps RTB'd.

Je soupçonne sournoise cela pourrait être causé par le fait que sa ressource, et cette ressource paresseuse n'est pas inline. Ainsi, une solution possible serait, en quelque sorte (???), la résolution de la force de toutes les références de ressources statiques avant de rendre. Mais je ne sais absolument pas comment faire.

Quelqu'un a une solution pour cela?

Était-ce utile?

La solution

Vous avez deux problèmes:

  1. Vous n'avez pas défini PresentationSource sur vos événements visuels afin Loaded ne se déclenche pas.
  2. Vous ne l'avez pas vider la file d'attente Dispatcher. Sans rinçage de la file d'attente Dispatcher, toute fonctionnalité qui utilise callbacks Dispatcher ne fonctionnera pas.

La cause immédiate de votre problème est l'échec de vider la file d'attente Dispatcher, car VisualBrush utilise, mais vous aurez probablement courir dans le problème PresentationSource avant longtemps donc je fixer les deux.

Voici comment je le fais:

// Create the container
var container = new Border
{
  Child = contentVisual,
  Background = Brushes.White,
  BorderBrush = Brushes.Black,
  BorderThickness = new Thickness(1),
};

// Measure and arrange the container
container.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
container.Arrange(new Rect(container.DesiredSize));

// Temporarily add a PresentationSource if none exists
using(var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(container)==null ? container : null) })
{
  // Flush the dispatcher queue
  Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));

  // Render to bitmap
  var rtb = new RenderTargetBitmap((int)b.ActualWidth, (int)b.ActualHeight, 96, 96, PixelFormats.Pbgra32);
  rtb.Render(container);

  return rtb;
}

Pour votre information, StaticResource recherche est jamais retardée en aucun cas: Il est traité au moment où le XAML est chargé et immédiatement remplacé par la valeur récupérée du ResourceDictionary. uniquement StaticResource façon pourrait peut être lié est si ramassé la mauvaise ressource parce que deux ressources ont la même clé. Je pensais juste que je devrais expliquer cela - il n'a rien à voir avec votre problème réel

.

Autres conseils

Et bien à elle ligne, vous pouvez simplement faire quelque chose comme ceci:

<Grid>
    <Grid.Background>
        <VisualBrush>
            <VisualBrush.Visual>
                <!-- blah blah -->
            </VisualBrush.Visual>
        </VisualBrush>
    </Grid.Background>
</Grid>

Si cela ne fonctionne pas, je pense serait que ce doit être quelque chose de spécifique avec l'instance de Visual que vous utilisez (ce qui exigera un code plus pour mieux diagnostiquer).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top