Tech/Silverlight2010. 6. 2. 12:04

내가 하고자 하는 것은, Rectangle이 이동하는 애니메이션을 갖고 있는 UserControl만 있는 프로젝트를 만들고, 그 프로젝트의 결곽물인 .xap 파일을 다른 프로젝트에서 동적으로 로딩하여 애니메이션을 볼 수 있도록 하는 것이다.

이 과정에서 나는 MEF를 이용할 것이다. 동적으로 .xap파일을 로딩하는 방법은 MEF말고도 있다. WebClient를 이용하여 .xap파일을 열어 Assembly 정보를 얻는 방법도 그 중 하나이다.

동적으로 .xap를 로딩하는 방법은 지난 포스팅에 소개했었다. (예제 따라해보기지만...)
우선 처음으로 할 일은 Rectangle이 이동하는 애니메이션을 갖고 있는 UserControl만 있는 프로젝트를 만드는 일이다.
나는 간단하게 Rectangle을 생성한 뒤, Rectangle이 좌측에서 우측으로 이동하면서 색깔이 변하는 Storyboard를 만들었다.
그 다음엔 애니메이션을 재생하고 있는 UserControl을 통째로 Export한다.

[Export("Animation", typeof(UserControl))]
public partial class AnimationControl : UserControl

"Animation"이라는 특정 이름과 UserControl 타입으로 외부에 노출한다는 것을 명시해주자. 그리고 빌드 한 후, .xap 결과물을 Import할 프로젝트의 ClientBin 폴더에 복사한다.
Import할 프로젝트로 이동하여, Import 짝꿍을 만들어주자. 지난 포스팅에도 말했었지만, 외부 .xap파일을 로딩하는 경우이므로 [ImportMany]를 사용한다.

[ImportMany("Animation", typeof(UserControl), AllowRecomposition = true)]
public IEnumerable<UserControl> AnimationCtrl { get; set; }

위와 같이 정의하면, AnimationCtrl에 아까 Export한 AnimationControl이 들어갈 것이다. 내가 원하는 것은 AnimationControl을 현재 프로젝트의 LayoutRoot에 추가하여 애니메이션을 보는 것이기 때문에, AnimationCtrl을 foreach문으로 돌려 AnimationControl의 정보를 추출해낸다. 이 작업을 .xap파일 다운로드가 완료되면 수행하도록 해준다.

Package.DownloadPackageAsync(new Uri("RectangleAnimation.xap", UriKind.Relative), (s, p) => 
{    
    catalog.AddPackage(p);    
    foreach (var item in AnimationCtrl)    
    {        
        this.LayoutRoot.Children.Add(item);    
    }
});

여기까지 했다면, 내가 찾던 UserControl이 현재 화면에 보이고, 애니메이션이 실행될 것이다. 난 여기에서 그치지 않고, 애니메이션 실행이 완료된 후, 메시지 박스를 호출하도록 하겠다. 그러기 위해선, 몇 줄 더 첨가해야한다.

Package.DownloadPackageAsync(new Uri("RectangleAnimation.xap", UriKind.Relative), (s, p) => 
{
     catalog.AddPackage(p);

     foreach (var item in AnimationCtrl)
     {
          EventInfo eInfo = (item.GetType()).GetEvent("Completed");
          Type handlerType = eInfo.EventHandlerType;
          Delegate d = Delegate.CreateDelegate(handlerType, null, this.GetType().GetMethod("OnCompleted"));

          eInfo.AddEventHandler(item, d);

          this.LayoutRoot.Children.Add(item);
          }
     }
);

분홍색 박스 친 부분들이 추가된 부분이다. 난 애니메이션을 포함하고 있는 UserControl 내에서 미리 애니메이션 실행이 완료되면 외부로 Completed 이벤트를 알리도록 만들어 놓았다. 그리고 외부에서 EventInfo를 이용하여, Completed로 정의된 이벤트 정보를 얻도록 한 후, Completed 이벤트가 발생하면, OnCompleted 함수를 호출하도록 연결하였다.

public void OnCompleted(object sender, EventArgs e)
{
    MessageBox.Show("Animation Complete");
}

그 이후, 간단하게 OnCompleted 에서 메시지 박스를 호출하면 끝!
참 쉽죠잉.

Posted by 알 수 없는 사용자