Avalondock + UnityContainer (1)

처음하는 C#이라 정리하면서 개념 좀 확실해 주입할려고 포스팅한다.

요구사항은
창들이 VisualStudio 처럼 docking 가능해야한다.
각 모듈은 가능한 독립적으로 개발 가능해야 한다.(협업)

나머지 요구사항은 지금 정리하고자 하는 내용과는 관계없어 일단 Dock 가능한 라이브러리와 패턴앤프랙틱스의 Composite Application Library 부분만 정리할려고 한다.

Avalondock 
  코드플렉스(http://avalondock.codeplex.com)에서 다운받을수 있으며 샘플이 제공된다. Visual Studio 와 같은 Dock 기능을 제공한다.

Composite Application Library
  CAB(Composite Application Block) 의 WPF 버전(http://msdn.microsoft.com/en-us/library/ff648611.aspx)으로 MVVM 패턴을 손쉽게 구현할수 있다. 요즘 많이 사용하는 프레임워크의 기본적인 IoC(Inversion of Control) , Container 등 내가 필요한 것만 있고, 적당한 예제가 있어서 선택했다. 그리고, EventAggregator 패턴이 구현되어 있어 모듈간 종속없이 통신할수 있어 결합도를 낮출수 있다.

1. 준비
VisualStudio(VS)에서 새프로젝트 만들기를 선택하고 템플릿에서 "WPF 응용프로그램"을 선택한다.

프로젝트가 생성되면 App.xaml 에서 StartupUri 를 제거한다.
Window1.xaml 을 제거하고 Shell.xaml을 추가한다.

다운받은 Avalondock Manger 와 CAL을 참조추가 해준다.( 프로젝트에 LIB를 만들어 DLL파일을 넣고 참조하였음)
Bootstrapper.cs 파일을 추가하고 UnityBootstrapper 를 상속받아 CreateShell을 구현한다.
public class Bootstrapper : UnityBootstrapper
    {
        protected override System.Windows.DependencyObject CreateShell()
        {
            var shell = Container.Resolve<Shell>();
            shell.Show();
            return shell;
        }
    }




App.xaml.cs 을 열고 OnStartup을 override 한다.

public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            Bootstrapper boot = new Bootstrapper();
            boot.Run();
        }
    }

이제 실행을 해보면 Bootstrapper가 실행되면서 Container가 Shell을 찾아 인스턴스를 만들고 화면에 우리가 만들 윈도우가 나타나게 된다. 하지만 Module이 하나도 없어 오류가 날것이다.

2. 모듈추가
솔루션에 새로운 프로젝트를 추가한다. 템플릿은 클래스 라이브러리를 선택한다.
참조추가하여 아까 추가한 LIB아래 DLL을 모두 추가한다.
자동으로 생성된 Class1.cs 를 ClockModule.cs 로 변경한다.
IModule을 구현하고, 생성자를 만들어준다.

public class ClockModule : IModule
    {
        IUnityContainer _Container;
        IRegionManager _RegionManager;
        #region IModule 멤버

        public ClockModule(IUnityContainer container, IRegionManager manager)
        {
            _Container = container;
            _RegionManager = manager;
        }

        public void Initialize()
        {
            
            var view = _Container.Resolve<ClockView>();
            

            _RegionManager.AddToRegion("MainRegion", view);
        }
        #endregion
    }


생성자의 Container와 RegionManager는 UnityContainer가 주입해 주므로 신경쓰지 않아도 된다. Initialize() 에서 view를 찾아 MainRegion에 추가해 준다.

먼저 View를 작성하자.  ClockModule 의 프로젝에 Views라는 폴더를 만들고 WPF 창을 ClockView라는 이름으로 추가한다. 그리고, xaml을 아래와 같이 수정한다.



<ad:DockableContent x:Class="Clock.Views.ClockView"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"

    Height="300" Width="300">

    <Grid>

        <Button>HELLO !!!</Button>

    </Grid>

</ad:DockableContent>


코드비하인드(ClockView.xaml.cs)도 열어 아래와 같이 수정한다.
public partial class ClockView : DockableContent


    {


        public ClockView()


        {


            InitializeComponent();


        }


    }
코드를 보면 알겠지만 DockingManager가 수용할 수 있는 창은 DockableContent이다. (물론 이외에도 몇가지 더있다.)


이제 컨테이너가 Module을 초기화 할수 있게 Bootstrapper를 수정하자. 아래 메소드를 오버라이드 한다.

protected override Microsoft.Practices.Composite.Modularity.IModuleCatalog GetModuleCatalog()

        {




            var catalog =  new ModuleCatalog();

            catalog.AddModule(typeof(ClockModule));




            return catalog;   

        }
그리고, Shell에서 dock이 가능하도록 dockmanager를 추가한다.

<Window x:Class="AvalonDockMVVM.Shell"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"

    xmlns:cal="http://www.codeplex.com/CompositeWPF"

    Title="Shell" Height="300" Width="300">

    <ad:DockingManager >

        <ad:DockablePane cal:RegionManager.RegionName="MainRegion">

        </ad:DockablePane>

    </ad:DockingManager>

</Window>
이제 실행해보면 거대한(?) Button이 하나 나오고 해당 버튼의 컨테이너를 float 할수 있다.




댓글

이 블로그의 인기 게시물

C#에서 포인터 사용

WPF RichTextBox 와 Document의 바인딩

WPF 이미지위에 라인 그리기(WPF DrawLine on exist Image)