툴의 꽃 프러퍼티 그리드를 사용해보자 ( PropertyGrid for WPF )

작업공간/C#/Winform/WPF 2012.06.22 23:17

이 글은 놀개영 http://www.gamedevforever.com 에서 같이 연재 되고 있는 글입니다.


게임을 제작하게 되면 게임에 등장하는 여러 오브젝트들을 만들게 됩니다. 그런데 이 오브젝트들은 많은 속성 값을 가지게 됩니다. 위치라든가, 크기, 속도, 텍스쳐는 어느 것을 쓰는지, 이 객체에 쓰일 이펙트는 어떤 것인지 같은 것 말입니다. 보통 이런 속성 값들은 툴을 이용해 제어하게 됩니다. 그런데, 이 속성 값들을 지정해주기 위해서는 입력 필드가 필요하겠지요?


윈폼이나 WPF에서는 체크박스, 텍스트박스 같은 기본 컨트롤등이 제공되고 있습니다. 이 컨트롤들을 이용해 위에서 말한 속성 값들을 정의 할 수 있습니다. 하지만 많은 수의 속성 값들을 제어 하기에는 역부족입니다. 각각의 오브젝트들이 같은 속성 값을 가지고 있는 것도 아니고, 오브젝트 종류에 따라 많게는 수십가지의 속성 값을 필요로 하는데 이 많은 속성 값들을 위한 입력 필드들을 재구성하고, 추가하는 것을 만들라 하면 누구라도 멘붕이 올 것입니다.


벌써 부터 하기 싫어진다...


수많은 속성 값들을 손쉽게 제어할수 있는 컨트롤이 있으면 어떨까요? 게다가 제작도 간편해야 합니다. 툴을 만들때 딱! 하니 뙇! 하고 나와주면 얼마나 좋겠습니까? 그런데 그게 실제로 존재합니다.


ㅋㅋㅋㅋ


그게 무엇인지 알아보기 전에 다른 이름 있는 게임 엔진 툴들은 이것을 어떻게 처리 하고 있는지 한번 살펴 보죠.






내노라 하는 게임 엔진들을 보면 항상 보이는 놈이있죠. 직접 툴을 만들어 보시면서 사용해보신 분들도 계실겁니다. 바로 프로퍼티 그리드 ( Property Grid )죠. 이 프로퍼티 그리드는 그 이름 답게 수많은 속성 값들을 제어할수 있게 도와주는 아주 유용한 컨트롤입니다. 특히 이 프로퍼티 그리드가 유용한 이유 중 하나가 바로 다양한 타입의 값들을 제어 할수 있다는 것입니다.


툴에서 사용되는 많은 속성 값들은 타입이 제각각 입니다. 단순 불린 ( Boolean ) 타입 부터 정수, 실수는 물론이고, Point, Vector3/4, 16진수 컬러값까지 다양한 값들이 존재합니다. 프로퍼티 그리드는 이런 다양한 타입들을 한 곳에서 제어할수 있는 수단을 제공해주죠. 불린은 체크박스 형태로, 스핀 컨트롤로 정교한 실수값 설정, 브러시 컨트롤을 이용한 색 추출, 그리고 포인트나 벡터 같이 동시에 다수의 값들이 필요한 타입까지도 말이지요.


좋습니다. 그렇다면 어떻게 해야 이 프로퍼티 그리드라는 놈을 내가 만드는 툴에 뙇~ 하고 넣을 수 있을까요? 안타깝게도 이 프로퍼티 그리드라는 놈은 WPF에서 기본으로 제공해주는 컨트롤이 아닙니다.


이런 고자 같은 WPF 같으니...


그렇다면 어떻게 WPF에서 프로퍼티 그리드를 사용해야 하는가? 고맙게도 이미 많은 능력자 분들께서 WPF에서 프로퍼티 그리드를 사용할수 있게 만들어 공개해두셨습니다. MS도 참 웃긴게 비쥬얼 스튜디오 Visual Studio 에서도 사용 되는 컨트롤을 왜 기본으로 제공 안해주는지 모르겠습니다(블렌드 Blend 같은 툴 팔아먹으려고 그러는 것 같아요).


일단 제가 찾아서 사용해본 몇몇 프로퍼티 그리드등이 있는데, 각각 구현 방식도 다르고, 비쥬얼도 다르지만 가장 제대로 작동하고, 사용하기 쉬웠던 것은 Jaime Olivares 라는 분이 만드신 Native WPF 4 PropertyGrid 였습니다.



프로퍼티 그리드를 사용하기 위해서는 먼저 C#의 프로퍼티에 대해 알아야합니다. 이 프로퍼티 기능은 C++ 식으로 말하면 일종의 Getter/Setter 인터페이스라고 할수 있습니다. 소스를 보시면 쉽게 이해 되실 겁니다.

public class Person
{
    public enum Gender { Male, Female }

    private string m_strName;
    private int m_iAge;
    private Gender m_eGender;

    public Person()
    {
        m_strName = "친절한티스";
        m_iAge = 21;
        m_eGender = Gender.Male;
    }

    public string nameProp
    {
        set { m_strName = value; }
        get { return m_strName; }
    }

    public int ageProp
    {
        set { m_iAge = value; }
        get { return m_iAge; }
    }

    public Gender genderProp
    {
        set { m_eGender = value; }
        get { return m_eGender; }
    }
}

멤버 변수는 private 으로 설정 되어있고, 그 멤버 변수에 대한 nameProp, ageProp, genderProp 프로퍼티들이 선언 되어있습니다. 외부에서 멤버 변수의 값을 쓰거나 읽을때 이 프로퍼티들을 이용하게 되죠.

Person prop = new Person();
prop.nameProp = "김포프";
prop.ageProp = 22;
prop.genderProp = Person.Gender.Female;

...이렇게 말이죠.


갑자기 C#의 프로퍼티 기능에 대해서는 왜 말하는 거지? 하고 의아해 하실 수 있는데, 프로퍼티 그리드가 바로 이 프로퍼티 기능을 이용하기 때문입니다. 게다가 무려 프로퍼티를 선언해 두면 프로퍼티 그리드에서 알아서 컨트롤에 생성을 해줍니다!!!!!!!


그렇다면 정말로 프로퍼티 그리드에 위의 속성값들이 나오는지 만들어보겠습니다. 두큰두큰~ 위에서 받은 WpfPropertyGrid.cs 파일을 프로젝트에 추가 해주고 아래 그림과 같이 프로젝트에 참조를 추가 해줍니다.



그리고 프로퍼티 그리드를 추가할 윈도우 xaml 파일을 열어 아래와 같이 추가해줍니다.



이제 프로퍼티 그리드에 표시해줄 속성 값을 가지고 있는 오브젝트를 생성해서 적용해주면 됩니다.

public MainWindow()
{
    InitializeComponent();

    Person prop = new Person();
    prop.nameProp = "김포프";
    prop.ageProp = 22;
    prop.genderProp = Person.Gender.Female;

    // 프로퍼티 그리드에 적용
    propertyGrid1.SelectedObject = prop;
}

끝입니다. 참쉽죠? 정말 제대로 나올까요? 한번 실행해보겠습니다.



22살의 아리따리운 미소녀 김포프 프로퍼티 그리드가 나타났습니다. 우왕~ 그런데 좀 이상하군요. 카테고리 분류도 없고, 속성값 이름도 프로퍼티 이름이 그대로 나옵니다. 다른 엔진 툴에서 사용되는 프로퍼티 그리드를 보면 카테고리도 잘 분류되어있고, 속성값 이름들도 그럴싸하게 명명되어 있는데 말이죠. 이를 바꿔주기 위해서는 C#의 Attributes를 이용해주어야 합니다.

public class Person
{
    public enum Gender { Male, Female }

    private string m_strName;
    private int m_iAge;
    private Gender m_eGender;

    public Person()
    {
        m_strName = "박기헌";
        m_iAge = 31;
        m_eGender = Gender.Male;
    }

    [Category("인적사항")]
    [DisplayName("이름")]
    public string nameProp
    {
        set { m_strName = value; }
        get { return m_strName; }
    }

    [Category("인적사항")]
    [DisplayName("나이")]
    public int ageProp
    {
        set { m_iAge = value; }
        get { return m_iAge; }
    }

    [Category("기타등등")]
    [DisplayName("성별")]
    public Gender genderProp
    {
        set { m_eGender = value; }
        get { return m_eGender; }
    }
}

Category와 DisplayName Attributes를 추가 하였습니다. 어떻게 바뀌었을까요?



카테고리가 생겼고, 속성 값명도 지정해준대로 잘 나옵니다. 짝짝짝~~

...계속


( 예상보다 내용이 너무 길어져서... 상하로 나눠서 써야 할것 같군요. 진짜 연재가 되어버렸네... )

저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글

  • 책읽는잉여 2012.06.25 09:56 신고 ADDR 수정/삭제 답글

    femail/22/김포프
    !?!?!?!?

  • BlogIcon 월하 2012.06.26 14:29 신고 ADDR 수정/삭제 답글

    Person prop = new Person();
    prop.nameProp = "김포프";
    prop.ageProp = 22;
    prop.genderProp = Person.Gender.Female;


    어... 아무리봐도 이상한데요? ㄷㄷㄷㄷ