2010-07-03 5 views
1

내 시나리오는 다음과 같습니다. 내 아들을위한 약간의 수학 퀴즈 응용 프로그램을 만들고 각 질문에 답한 후 내 캔버스의 배경 ImageBrush를 동적으로 변경하려고했습니다. 내 이미지 (pngs)를 리소스 파일에 삽입하고 배열에로드 한 다음 무작위로 하나를 선택하여 캔버스에로드하는 것으로 생각했습니다.런타임 중에 WPF에서 Canvas의 배경을 변경하려면 어떻게해야합니까?

내가 처음 만난 문제는 리소스 파일에서 이미지가 비트 맵으로 저장된다는 사실이었습니다. 일부는 인터넷에서 둘러보고 난 후에 나는 마침내 그 다음 도우미 메서드 사용하여 객체를 BitmapImage하는 비트 맵 변환하는 방법을 알아 냈 : 나는 BitmapImage에서 ImageBrush와를 만들어 거기에서

private BitmapImage FromResourceBitmap(Bitmap bitmap) 
    { 
     var result = new BitmapImage(); 

     using(var stream = new MemoryStream()) 
     { 
      bitmap.Save(stream, ImageFormat.Png); 

      stream.Position = 0; 

      result.BeginInit(); 
      result.StreamSource = stream; 
      result.EndInit(); 
     } 

     return result; 
    } 

을하고 배경에 할당 캔버스의 속성 :

  var brush = new ImageBrush {ImageSource = m_Media.Screens[0]}; // m_Media.Screens[x] returns a BitmapImage...obviously. 
      QuestionCanvas.Background = brush; 

불행히도, 이것은 작동하지 않는 것 같습니다. 응용 프로그램이 실행될 때 배경은 순수한 흰색입니다. 내 XAML은 배경을 설명하지 않고 ... 잘 혼란 스럽습니다. 어떤 도움이라도 대단히 감사하겠습니다! 고맙습니다!

+0

백그라운드 속성을 변경 한 후에 창 크기를 조정하려고하면 어떻게됩니까? 내 직감은 그것이 새로 고침 문제라고합니다. 그 외에는 그 방법에 문제가있을 수 있습니다. 정적 리소스를 먼저 사용하도록 설정하십시오. 단단한 경우 메서드에서 직접 시도하고 수행 할 수 있습니까? – keyle

+0

그것이 내가 원래 생각한 것입니다. 어떤 "무효화"메서드를 호출하여 다시 그리기를 시도했지만 아무 일도 없었습니다. 크기 조정, 최소화, 최대화 등은 아무 것도하지 않았습니다. 그러나, 나는 그것을 밖으로 생각하고 몇 분 안에 답변을 게시 할 것입니다. – Mateo

답변

0

다양한 ImageBrush 관련 클래스, 특히 BitmapImage의 클래스를 살펴본 결과, StreamSource 속성이 BitmapImage 객체 내에서 로컬 복사본을 만드는 대신 단순히 스트림을 참조하고 있다고 생각하기 시작했습니다. 따라서 헬퍼 메서드 내에서 using 문을 사용하면 스트림이 실제로 해제되어 BitmapImage의 StreamSource가 null이됩니다. 그 다음 캔버스는 평범한 흰색 (#FFFFFFFF) SolidColorBrush로 떨어졌습니다 (제게 Snoop을 상기시켜 주신 Thanks James).

그래서이 문제를 해결하기 위해 다양한 이미지 스트림에 대한 참조를 보유하기 위해 개인 목록을 만든 다음 내 BitmapImages를 해당 참조로 지정합니다. GC를 사용할 때 다양한 MemoryStream을 출시하기 위해 IDisposable을 구현했습니다. 여기에 단축 코드 : 여기

public class Media : IDisposable 
{ 
    private readonly List<BitmapImage> m_Screens = new List<BitmapImage>(); 
    private readonly List<MemoryStream> m_BackingStreams = new List<MemoryStream>(); 

    public BitmapImage MainScreen { get; private set; } 

    public List<BitmapImage> Screens 
    { 
     get 
     { 
      return m_Screens; 
     } 
    } 

    public Media() 
    { 
     LoadScreens(); 
    } 

    private void LoadScreens() 
    { 
     m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_01)); 
     m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_02)); 
     m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_03)); 
     m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_04)); 
     m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_05)); 

     foreach (var stream in m_BackingStreams) 
     { 
      m_Screens.Add(FromResourceStream(stream)); 
     } 
    } 

    private BitmapImage FromResourceStream(Stream stream) 
    { 
     var result = new BitmapImage(); 

     result.BeginInit(); 
     result.StreamSource = stream; 
     result.EndInit(); 

     return result; 
    } 

    private MemoryStream FromResourceBitmap(Bitmap bitmap) 
    { 
     var stream = new MemoryStream(); 

     bitmap.Save(stream, ImageFormat.Png); 

     return stream; 
    } 

    public void Dispose() 
    { 
     if (m_BackingStreams.Count == 0 || m_BackingStreams == null) return; 

     foreach (var stream in m_BackingStreams) 
     { 
      stream.Close(); 
      stream.Flush(); 
     } 
    } 

그리고 것은 실제로 런타임 동안 내 캔버스의 배경을 설정할 때 어떻게 생겼는지입니다 : 그것을 고정

MainMenuCanvas.Background = new ImageBrush(m_Media.Screens[0]); 

, 우아대로 될 수있다.

나는 MSDN에 BitmapImage.StreamSource 문서 페이지에서 정보의이 조금 건너 않은 연구하는 동안 :

당신이 를 원하는 경우 후 스트림을 닫습니다 BitmapCacheOption.OnLoad에 CacheOption 속성을 설정

BitmapImage가 생성되었습니다. OnDemand 캐시 옵션은 비트 맵이 이 될 때까지 액세스를 유지하고 가비지 수집기로 처리합니다.I는 BitmapCacheOption.OnLoad 할 CacheOption 열거 세트 원액을 사용하려고 할 때

(http://bit.ly/bitmapimagestreamsource)

그러나, 동일한 문제가 발생했습니다. 나는 여기서 뭔가를 놓칠지도 모른다. 그러나 명백한 것은 그렇게 추측하지 않는다. :)

1

아마도 캔버스가 투명하거나 아마 캔버스 위에 다른 요소가 있는지 궁금합니다. 시각적 트리를보고 정확히 무슨 일이 일어나는지 확인하기 위해 Codeplex의 Snoop을 살펴볼 것입니다. 또한 다음 질문으로 이동할 때 트리거 또는 코드 바인딩을 사용하여 이미지를 설정하는 것도 고려하십시오. 그런 다음 트리거를 사용하여 템플릿에 배경을 바인딩하거나 이미지를 보유하고있는 항목을 자동으로 업데이트 할 수 있습니다.

+0

스눕을 생각 나게 해 주셔서 감사합니다! – Mateo

관련 문제