2012-02-29 2 views
0

У меня есть код, который предназначен для визуализации ControlTemplate в writeableBitmap. Код для создания WBMP выглядит следующим образом:Silverlight 4 Render to WriteableBitmap возвращает пустую растровую карту

private static void OnMarkerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var template = e.NewValue as ControlTemplate; 
     if (template != null) 
     { 
      var c = new Marker(); 
      c.Template = template; 
      c.ApplyTemplate(); 
      c.MeasureArrange(); 
      c.Width = c.DesiredSize.Width; 
      c.Height = c.DesiredSize.Height; 

      // _cachedBitmap is of type WriteableBitmap 
      _cachedBitmap = c.RenderToBitmap(); 
     } 
    } 

Где определены следующие методы расширения:

internal static void MeasureArrange(this UIElement element) 
    { 
     element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
     element.Arrange(new Rect(new Point(0, 0), element.DesiredSize)); 
    } 

    public static WriteableBitmap RenderToBitmap(this FrameworkElement element) 
    { 
     int width = (int)element.DesiredSize.Width; 
     int height = (int)element.DesiredSize.Height; 

#if SILVERLIGHT 
     var result = new WriteableBitmap(width, height); 
     result.Render(element, new TranslateTransform()); 
     result.Invalidate(); 
     return result; 
#else 
     // WPF Impl works just fine 
     var bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); 

     bmp.Render(element); 
     return new WriteableBitmap(bmp); 
#endif   
    } 

и маркер определяется как пустой контроль

public class Marker : Control 
{   
} 

вопрос это. В WPF все работает отлично, как в Silverlight после первой попытки создания растрового изображения. Однако первая попытка не удалась, возвращая WriteableBitmap правильного размера (7 * 7 или 49 пикселей), но со всеми нулями в массиве int[] Pixels.

Некоторые вещи, которые могут быть полезны. Непосредственно перед созданием WriteableBitmap в RenderToBitmap ширина/высота элемента равна 7,7, желаемый размер равен (7,7), а ActualWidth/ActualHeight равен (0,0). В WPF я считаю, что все это (7,7). Таким образом, это может быть вопрос размещения не

FYI Marker и ControlTemplate никогда не попадают в визуальное дерево. Это чисто кэшированная реализация растрового изображения.

Любые идеи?

ответ

0

Aha! Я нашел ответ. Хотя я не знаю, почему. «Ответ» тикает идет к любому, кто может это объяснить.

Я нашел this link, который предлагает ActualWidth/ActualHeight оцениваться асинхронно, поэтому хорошо спроектированный BeginInvoke может решить проблему. Почему это работает в WPF, но не в Silverlight?

 var c = new PointMarker(); 
     c.Template = pointMarkerTemplate; 
     c.ApplyTemplate(); 

     // DispatcherUtil is just a proxy around Dispatcher.BeginInvoke 
     DispatcherUtil.Instance.BeginInvoke(() => 
     { 
      c.MeasureArrange(); 
      c.Width = c.DesiredSize.Width; 
      c.Height = c.DesiredSize.Height; 
      series._pointMarkerCache = c.RenderToBitmap(); 
      series.OnInvalidateParentSurface(); 
     }); 
+1

Вероятно, Silverlight прохода измерения, который вычисляет ActualWidth/ActualHeight является первым сбросом тех 0 до перерасчета новых значений и устанавливать их перед возвращением. Поэтому я предполагаю, что если ваш код выполняется в другом потоке, чем этот код, вы можете прочитать значения во время пересчета и, таким образом, прочитать 0. Однако это будет случай, если какое-то событие изменения размера вызывает перерасчет, не видно, почему он будет постоянно пересчитывать эти ценности –

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