2012-02-29 2 views
0

ControlTemplate을 쓰기 가능 비트 맵으로 렌더링하기위한 몇 가지 코드가 있습니다.Silverlight 4 Render to WriteableBitmap은 빈 비트 맵을 반환합니다.

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 
{   
} 

으로 정의된다 : 다음과 같은 확장 방법을 정의

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

을 다음과 같이 WBMP를 작성하는 코드는 이. WPF에서는 비트 맵을 만드는 첫 번째 시도 후에 Silverlight에서와 마찬가지로이 모든 것이 올바르게 작동합니다. 그러나 첫 번째 시도가 실패하고 올바른 크기 (7 * 7 또는 49 픽셀)의 WriteableBitmap을 반환하지만 int[] Pixels 배열의 모든 0을 반환합니다.

도움이 될만한 몇 가지 사항이 있습니다. WriteableBitmap을 생성하기 바로 전에 RenderToBitmap에서 요소의 너비/높이는 7,7이고 원하는 크기는 (7,7)이지만 ActualWidth/ActualHeight는 (0,0)입니다. WPF에서 저는 모든 것이 (7,7)라고 믿습니다. 따라서 이것은 레이아웃 문제가 아닐 수 있습니다.

참고 사항 Marker 및 ControlTemplate은 시각적 트리를 만들지 않습니다. 이것은 순전히 캐시 된 비트 맵 구현입니다.

아이디어가 있으십니까?

답변

0

아하! 나는 대답을 찾았다. 나는 왜 그런지 모르지만. "답"은 그것을 설명 할 수있는 누구에게나갑니다.

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

아마도 ActualWidth/ActualHeight를 계산하는 Silverlight 측정 단계는 새 값을 다시 계산하고 반환하기 전에 먼저 해당 값을 0으로 다시 설정합니다. 그래서 만약 당신의 코드가 그 코드보다 다른 쓰레드에서 실행된다면 재 계산 도중 값을 읽어서 0을 읽을 수도 있습니다. 그러나 일부 크기 조정 이벤트가 발생하여 재 계산이 발생했는지, 왜 보이지 않는지는 알 수 없습니다. 항상 그 값들을 다시 계산할 것입니다. –