[.NET] C#을 이용한 PropertyGrid 사용법에 대한 Summary

이제 PropertyGrid 컨트롤의 프로퍼트에 이미지 컴보 리스트를 달아보자. 아래의 결과처럼 말이다.
먼저 PropertyGrid의 SelectedObject에 할당될 프로퍼티를 정의할 클래스를 만들어 주어야 한다. 즉 우리가 지금 정의할 클래스에는 위의 그림에서처럼 SourceType이라는 프로퍼티에 대한 정보를 담고 있을 것이다. 아래의 코드가 바로 그 클래스이다. 클래스 명은.. 딱히 지을만한게 없어 개똥이클래스라고 하려다가 그냥 얌전하게 MyProperty라고 이름 붙였다. (C#에서는 클래스명이나 변수명을 한글로 할 수 있다)

public class MyProperty {
    private MyType _type;

    [Editor(typeof(MyPropertyGridEditor), 
            typeof(System.Drawing.Design.UITypeEditor))]
    public MyType SourceType
    {
        get { return _type; }
        set { _type = value; }
    }
}

일단 MyType이라는 새로운 Type이 있는데, 이 Type은 아래와 같다.

public enum MyType { Left, Right, Up, Down };

실제로 PropertyGrid에 나타날 프로퍼티의 값으로 Left, Right, Up, Down이 나타날 것이다. 앞서 언급한 그림을 보기 바란다. 그리고 새롭게 등장한 Attribute 지시자로 Editor가 있는데, 이는 프러퍼티의 값을 변경할 UI Editor를 지정하기 위한 것이며, 인자로 2개를 받는다. 첫번째 인자는 UITypeEditor에서 상속받은, 곧 바로 우리가 새롭게 정의할 클래스명이고, 두번째 인자는 그냥 UITypeEditor 클래스명을 주면된다. 이렇게 Editor 특성자를 프로퍼티에 지정해주면 지정된 프로퍼티에 대한 값을 설정하기 위한 UI가 지정된다. 이 방법은 추후에 새롭게 살펴볼 프로퍼티의 값을 설정하기 위해 사용자 정의 UI를 붙이는 방법과 매우 유사하다.

이제 UITypeEditor에서 상속받아 새롭게 정의한 MyPropertyGridEditor에 대해서 살펴보도록하자.

public class MyPropertyGridEditor : UITypeEditor
{
    public override bool GetPaintValueSupported(
        ITypeDescriptorContext context) {
            return true;
        }

    public override void PaintValue(PaintValueEventArgs e) {
        string m = this.GetType().Module.Name;
        m = m.Substring(0, m.Length - 4);
        ResourceManager resourceManager =
            new ResourceManager(m + ".MyResource", 
                Assembly.GetExecutingAssembly());

        int i = (int)e.Value;
        string sourceName = "";
        switch (i) {
            case ((int)MyType.Left): sourceName = "left"; break;
            case ((int)MyType.Right): sourceName = "right"; break;
            case ((int)MyType.Up): sourceName = "up"; break;
            case ((int)MyType.Down): sourceName = "down"; break;
        }

        Bitmap newImage = (Bitmap)resourceManager.GetObject(sourceName);
        Rectangle destRect = e.Bounds;

        destRect.X = (e.Bounds.Width - newImage.Width) / 2;
        destRect.Y = e.Bounds.Y - 1;
        destRect.Width = newImage.Width;
        destRect.Height = newImage.Height;

        newImage.MakeTransparent();
        e.Graphics.DrawImage(newImage, destRect);
    }
}

제법 길다? -o-; ㅋ

먼저 이 클래스는 두개의 override된 매서드가 있다. 하나는 GetPaintValueSupported이며 또 하나는 PaintValue이다. 이 두개는 종속적인데 GetPaintValueSupported에서 true를 반환하면 PaintValue라는 매서드를 개발자가 override하겠다는 의미이다. 또한 바로 이 PaintValue 매서드에서 컴보 리스트에서 실제로 그림을 그려준다. 만약 GetPaintValueSupported가 false를 반환하면 그림이 없는 단순히 문자만 나타는 컴보 리스트의 형태로 나타난다. 아래의 그림처럼 말이다.
그렇다면 이제 PaintValue 매서드에 대해 집중해보자. 이 매서드는 내용은 이렇다. 먼저 IDE에서 추가한 리소스(MyResource.resx로 지정했음)에 접근할 수 있는 ResourceManager 클래스의 인스턴스를 얻는 코드의 부분이 있는데, 빨강색이 바로 그 코드이다. 아래의 그림을 참조하면 이해하기가 쉬울것이다.

그리고 이렇게 얻은 ResourceManager를 통해 현재 사용 컴보 리스트에 그려질 이미지를 얻어오는 코드가 초록색이다. 끝으로 빨강색 코드는 이렇게 얻어온 이미지를 화면상에 그린다. 그릴 영역은 PaintValue의 인자로 넘어온 PaintValueEventAgrs e를 통해서 얻을 수 있는데, 바로 e.Bounds이다.

음… 바로 지난번에 알아본 문자열에 대한 컴보 리스트 박스를 프로퍼티에 붙이는 것에 비하면 무척 쉽다고 생각한다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다