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

드디어 마지막으로 PropertyGrid의 속성을 변경하기 위한 사용자 정의 UI를 붙여보는 것에 대해 살펴 보겠다. 우리가 구현할 결과물의 최종 화면은 아래와 같다.


즉, MyValue라는 프로퍼티의 값을 설정하기 위해 TrackBar 컨트롤을 이용해 보는 것이다. TrackBar를 이용해 값을 설정한 후에 확인 버튼을 누르면 설정된 값이 프로퍼티에 반영이 되도록한다.

순서야 개발자 나름이겠지만, 설명의 편의를 위해 먼저 사용자 정의 UI에 해당하는, 즉 TrackBar 컨트롤과 확인 버튼, 그리고 라벨을 담고 있는 폼을 하나 정의한다.


여기서 TrackBar 컨트롤의 접근자를 원래의 Private에서 Public으로 변경한다. 이는 외부의 클래스에서 접근할 수 있도록 하기 위해서이다. 그리고 이겋게 추가한 폼의 이름을 frmMyValue라고 정하고, 이 폼의 속성을 아래와 같이 변경한다.

+ FormBorderStyle – None
+ MinimizeBox – False
+ MaximizeBox – False
+ ShowInTaskbar – False

위의 속상은 속성창을 통해서 수정이 가능하다. 하지만 변경해야할 속성이 하나 더 있는데, 이 속성은 속성창에서 볼 수 가 없다. 그 속성은 TopLevel이라는 속성으로 이 값을 이 폼의 색성자에서 false로 설정해야 한다. 이 것은 매우 중요하다. 이 값을 설정하지 않으면 프로퍼티에 우리의 사용자 폼이 붙지 못하기 때문이다.

그리고 변수를 2개 추가한다. PropertyGrid의 특정 프로퍼티와 통신을 할 수 있는 수단이 되는 IWindowsFormEditorService라는 인터페이스 변수인 _wfes와 TrackBar 컨트롤을 조작하여 얻은 값을 저장할 변수인 int 형의 MyValue을 추가한다.

이렇게 변수와 몇가지 설정이 끝났다면 이제 UI의 행위에 해당하는 매서드를 정의해야하는데, 아래의 코드로 그 설명을 대신한다.

public partial class frmMyValue : Form
{
    public int MyValue;
    public IWindowsFormsEditorService _wfes;
        
    public frmMyValue()
    {
        InitializeComponent();
        TopLevel = false;
    }

    private void frmMyValue_Load(object sender, EventArgs e)
    {
        label1.Text = "Value : " + MyValue;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        MyValue = trackBar1.Value;
        label1.Text = "Value : " + MyValue;
    }

    private void frmMyValue_FormClosed(object sender, 
        FormClosedEventArgs e)
    {
        _wfes.CloseDropDown();
    }
}

잘 살펴보면 어렵지 않게 코드를 이해할 수 있을 것이다. 그러나 한가지 새로운 것이 있는데 폼이 닫힐때(Close)할때 발생하는 이벤트에서 앞서 정의한 IWindowsFormEditorService 타입의 변수인 _wfes의 CloseDropDown 매서드를 호출하였다. 이것은 이 폼이 닫힐때 마친가지로 PropertyGrid의 프로퍼티에 붙은 사용자 정의 폼을 담을 컨테이너을 닫도록 하는 코드이다. 폼이 닫혔으므로 이 폼을 담을 컨테어너 역시 닫여야 하지 않겠는가.

이제 프로퍼티에 대한 정의를 담고 있는 클래스를 만들어보자. 이 클래스의 이름은 편의상 MyProperty라고 하였다. 추후 이 클래스의 인스턴스는 PropertyGrid의 SelectedObject에 할당된다.

public class MyProperty {
    private int _value;

    [Browsable(true)]
    [Editor(typeof(MyValueEditor), typeof(System.Drawing.Design.UITypeEditor))]
    public int MyValue
    {
        get { return _value; }
        set { _value = value; }
    }
}

MyProperty 클래스는 MyValue라는 프로퍼티 하나만 정의하고 있으모 이 프로퍼티에 대한 특성 중에 Editor 특성자에 대한 인자의 내용으로 MyValueEditor와 UITypeEditor의 type을 사용하고 있다. MyValueEditor은 UITypeEditor에서 상속받아 우리가 새롭게 정의할 클래스이다. MyValueEdior 클래스의 코드가 그렇게 길지 않으니 한번에 살펴보기로 하자.

public class MyValueEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(
        ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context,
        IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService wfes = provider.GetService(
            typeof(IWindowsFormsEditorService)) 
                as IWindowsFormsEditorService;

        if (wfes != null)
        {
            frmMyValue _frm = new frmMyValue();

            _frm.trackBar1.Value = (int)value;
            _frm.MyValue = _frm.trackBar1.Value;
            _frm._wfes = wfes;

            wfes.DropDownControl(_frm);
            value = _frm.MyValue;
        }

        return value;
    }
}

이 클래스는 GetEditStyle이라는 매서드와 EditValue라는 매서드를 재정의하고 있다. GetEditStyle은 프로퍼티에 붙을 사용자 정의 UI를 나타내기 위해 누를 버튼의 모양을 결정하는 것으로 할당할 수 있는 값은 모두 3가지 이다. 하나는 DropDown이며 삼각형 문자가 담긴 버튼이고 두번째는 Modal이며 … 문자가 담긴 버튼이며 세번째는 None로써 버튼 자체가 생기지 않는다. 이렇게 되면 사용자 정의 UI를 나타낼 방법이 없다. 여기서는 DropDown을 사용하였다. 그리고 EditValue는 사용자 정의 UI를 보이는 시점에서부터 사라질때까지의 영향을 미치는 매서드이다. 과정을 살펴보면 IWindowFormsEditorService 타입의 서비스 인스턴스를 구해 일단 wfes라는 변수에 담아 놓는데, 이는 앞서 정의한 폼(frmMyValue)의 맴버 변수인 _wfes에 참조시켜 실제적으로 프로퍼티와 사용자 UI을 연결짓는 중요한 역활을 하게된다. 그리고 EditValue는 정의한 frmMyValue 폼을 생성시키고 TrackBar 컨트롤을 초기화한 후에 IWindowsFormsEditorService의 DropDownControl을 호출함으로써, 이 시점에서 사용자 정의 UI를 화면에 보이도록 한다. 이 시점에 사용자 정의 UI가 화면상에서 사라질때까지 Blocking된다. 사용자 폼이 사라지면 EditValue 매서드의 인자인 value에 사용자 정의 UI에서 설정한 값을 담고 반환한다. 다소 무리한 설명이라고 생각되나 다시금 찬찬이 읽어본후 코드를 살펴보면 이해가 수월할 것이다. 이상으로 C#을 이용해 PropertyGrid를 이용하는 것에 대해 정리해보았다.

[.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이다.

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

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

앞서 언급한대로, PropertyGrid에 List 컨트롤을 달아보자. 이 글을 쓰기에 앞서 List 컨트롤을 PropertyGrid에 달아보는 샘플 코드를 작성하면서, 뭐.. “이런 뷁스런”이란 생각이 들었다. 단지 컨트롤 하나 달기 위해 전역 변수이며 새로운 클래스를 2개씩이나 만들어줘야하다니.. .NET에 대한 실망이 쪼끔 인다. 그러나 이 방법말고 좀더 세련된 방법이 있을것이라 생각된다. 한번 시간날때 찾아봐야겠다.

여하튼, 지금 내가 알고 있는 방법을 정리해보자. 먼저 구현할 결과 화면은 다음과 같다.

즉, 우리가 추가할 프로퍼티의 이름은 ItemName이고 이 프로퍼티의 값으로 사과, 귤, 포도, 망고, 딸기을 선택할 수 있는 Combo List 컨트롤이라는 도우미를 붙인 형태를 구현하는 방법이다.

먼저 사과, 귤, 포도 등의 문자열들을 담을 string 배열에 대한 전역 변수를 선언한다.

internal class PropertyItemList
{
    internal static string[] _items;
}

비록 PropertyItemList라는 클래스를 전역변수로써 인스턴스화하지는 않겠지만, 맴버변수로 정적으로 선언함으로써 전역변수의 의미를 갖는다. 이렇게 정적으로 선언하여 전역처럼 쓰는 이유는 앞으로 추가할 2개의 새로운 클래스에서 이 PropertyItemList의 _items 정적변수에 접근해야하기 때문이다. 추가할 2개의 새로운 클래스에 대해서 살펴보기 전에 PropertyItemList의 _items 변수에 문자값들을 넣어주는 코드의 살펴보자.

private void Form1_Load(object sender, EventArgs e)
    {
        MyList listItem = new MyList();

        PropertyItemList._items = new String[5];
        PropertyItemList._items[0] = "사과(Apple)";
        PropertyItemList._items[1] = "귤(Orange)";
        PropertyItemList._items[2] = "포도(Grape)";
        PropertyItemList._items[3] = "망고(Mango)";
        PropertyItemList._items[4] = "딸기(Strawbery)";

        propertyGrid1.SelectedObject = listItem;
}

MyList는 앞으로 추가할 2개의 클래스 중 하나이며, propertyGrid의 SelectedObject 속성에 넣어주게 된다. 이는 이미 앞서 살펴봤으므로 이미 잘알고있을것이다.

이제 새로운게 추가할 두개의 클래스를 하나 하나 만들어 보자. 먼저 이미 나와버린 MyList 클래스이다.

public class MyList {
    private string _itemName;

    [Browsable(true)]
    [TypeConverter(typeof(MyConverter))]
    public string ItemName {
        get {
            string S = "";
            if (_itemName != null) {
                S = _itemName;
            } else {
                S = PropertyItemList._items[0];
            }

            return S;
        }

        set { _itemName = value; }
    }
}

ProperrtGrid에 추가할 프러퍼티인 ItemName을 가지고 있으며 Attribute를 지정하고 있다. 여기서 지정된 Attribute에 대해서 살펴보면, Browsable와 TypeConverter이다. Browsable는 원래 지정하지 않아도 되는데, 기본값으로 true이기 때문이다. 의미그대로 PropertyGrid에 나타낼 것이냐 말것이냐를 정하는 것이다. 그리고 TypeConverter가 바로 우리가 추가한 프로퍼티에 리스트 컨트롤을 달게 하는 역활을 하는 Attribute이다. 즉, TyperConverter의 인자로써 어떤 클래스를 주는데, 바로 이 어떤 클래스를 통해 프로퍼티에 리스트 컨트롤을 달거나 프로퍼티를 사용자가 직접값을 수정하게 하거나 리스트 컨트롤에서 선택만 하게 하거나 등의 특성을 지정하는 것이다. 그렇다면 이제 마지막으로 이 어떤 클래스인 MyConverter에 대해 살펴보자.

public class MyConverter : StringConverter
{
    public override bool GetStandardValuesSupported(
        ITypeDescriptorContext context) {
        return true;
    }

    public override bool GetStandardValuesExclusive(
        ITypeDescriptorContext context) {
	return true;
    }

    public override 
        System.ComponentModel.TypeConverter.StandardValuesCollection
        GetStandardValues(ITypeDescriptorContext context) {
        return new StandardValuesCollection(PropertyItemList._items);
    }
}

다소, 뷁스러운 클래스라고 생각하는데, 이 하나의 클래스에서 생전보도 못한 .NET 클래스가 참 많이도 나오기 때문이다. 다 집어치우고 필요한 것만 골라 따져보면, 먼저 override한 GetStandardValuesSupported에서 true를 반환해야만 Combo List 컨트롤을 볼수가 있으며 false를 반환하면 우리의 노력은 물거품이 되고 만다. 그리고 GetStandardValuesExclusive라는 매서드의 반환값을 true로 하면 단시 List에서 선택만 할 수 있고 키보드로 문자열값을 변경할 수 없게된다. 마지막으로 GetStandardValues는 List 컨트롤에 나열된 문자열값을 지정해주기 위한 매서드이다.

필자는 “뭔가 잘못된 것 같다”라는 생각이 들었다. 단지 컴보 리스트 컨트롤 하나 추가하기 위한 과정이 이처럼 복잡하다는 이유에서가 아니라, 반드시 전역변수를 선언해야만(여기서는 같은 효과를 위해 정적변수를 선언했다) 한다는 것에서였다. 이 문제는 차츰 해결될 것이라고 생각된다.

끝으로 Blog에 어제부터 google의 AdSense를 달아놨는데.. 이 글이 도움이 되셨다면 댓글말고, 옆에 AdSense 클릭 좀 해주시길~ 댓글은 쓰기 힘드실까봐~ ㅋ –;;

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

일단 생긴 것 부터가 범창치 않은 이 컨트롤은 활용하기에 따라서 큰 활용도가 있을 것이다. 아래는 Visual Studio.NET 2005에 붙어 있는 속성창으로써 95% 이상이 PropertyGrid라는 컨트롤로 만들어진 UI이다.


필자가 이 PropertyGrid에 큰 관심을 두는 까닭은 VS의 속성창에 해당하는 델파이의 Object Inspector에 대한 필요성에서였다. 델파이의 Object Inspector 역시 PropertyGird와 같은 기능을 하는 VCL 컴포넌트로 만들어진 UI인데, 델파이의 개발사인 볼렌드는 해당 컴포넌트를 공개하지 않고 내부적으로만 사용하여왔으며, 지금 역시 그러하다. 그래서 필요하다면 천상 만들어 쓰던지, 어디서 찾아 쓰던지 사던지 해야할 것이였다. 이런 기능을 하는 컴포넌트를 하나 만들자니 배보다 배꼽이 더 커져버리게 될 모냥이고, 찾아 쓰자니 기존의 Object Inspector에 의해 눈이 높아져버려 마음에 드는 녀석을 찾아볼 수가 없었다. 그런데 MS는 PropertyGrid 컨트롤을 그냥 기본적은 .NET 컨트롤군에 포함시켜 사용자들이 쉽게 사용할 수 있도록 공개해 놓았다. MS의 개발자 지원에서 얼마나 큰 힘을 실고 있는지를 볼 수 있는 또 하나의 해석이라고 보여진다.

기능이 다양하고 강력한 만큼 PropertyGrid 컨트롤은 사용하기가 그렇게 호락 호락 하지 않은 녀석이다. .NET 기술이 태동되기 이전인 ATL 기술에서 채용되기 시작한 Attribute 방식을 사용하여 .NET에서 PropertyGrid를 사용한다. OOP 방식과 Attribute 방식 만남이다.

여기서는 기본적인 PropertyGrid의 사용법에서 고급사용법까지 몇단계에 걸치 그 사용법을 정리하고자 한다. 먼저 기본적인 사용법을 알아보겠다. 기보적인 사용법을 알아보기 위해 하나의 예제를 작성해 볼 것이다. 또한 그 예제의 결과 화면은 아래와 같다.


일단 Category는 ID Settings와 Marketting Settings로 2개이다.  ID Settings는 Address, Age, DateOfBirth, Name, SSN, TestColor이라는 이름의 Property를 가지고 있으며, Marketting Settings는 Email과 FrequentBuyer이라는 프로퍼트를 가지고 있다.

먼저 PropertyGrid의 사용법에 대한 큰 개념은 이렇다. Category를 지정하고 지정된 Category에 속하는 속성명과 속성의 Type을 지정하는 하나의 class를 만든 후, PropertyGrid의 SelectedObject에 그 class의 인스턴스를 할당한다. 이것이 전부다. SelectObject에 class의 인스턴스를 할당하는 거야 간단한 것이고, 문제는 그 문제의 class를 만드는 것이다. 바로 이 class를 만드는 것에 대해 살펴보자.

문제의 class의 빼대는 아래와 같다.

public class Customer
{
    private string _name;
    private int _age;
    private DateTime _dateOfBirth;
    private string _SSN;
    private string _address;
    private string _email;
    private bool _frequentBuyer;
    private Color _color;

    public Customer() {}
}

_name, _age, _dateOfBirth, _SSN, _address, _email, _frequentBuyer, _color이라는 변수들은 앞서 살펴본 구현할 결과 Property에 하나 하나가 매칭된다. 그러나 여기에는 크게 2가지 문제점이 있다. _name, _age등의 접근자는 private이므로 PropertyGrid는 이 변수들을 읽어낼 수도 변경할 수도 없다. 그래서 PropertyGrid와의 소통을 위해서 이 변수들에 대한 Property 지시자를 통해 Property로 만들어보자. 그 코드는 아래와 같다.

public class Customer
{
    private string _name;
    private int _age;
    private DateTime _dateOfBirth;
    private string _SSN;
    private string _address;
    private string _email;
    private bool _frequentBuyer;
    private Color _color;

    public Customer()  {}

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public Color TestColor
    {
        get { return _color; }
        set { _color = value; }
    }

    public string SSN
    {
        get { return _SSN; }
        set {_SSN = value; }
    }

    public string Address
    {
        get { return _address;}
        set {_address = value; }
    }

    public DateTime DateOfBirth
    {
        get {return _dateOfBirth; }
        set {_dateOfBirth = value; }
    }

    public int Age
    {
        get { return _age; }
        set {_age = value; }
    }

    public bool FrequentBuyer
    {
        get {return _frequentBuyer; }
        set { _frequentBuyer = value; }
    }

    public string Email
    {
        get { return _email;}
        set {_email = value;}
    }
}

이렇게 해서 데이터를 Property화하여 외부와의 데이터 통신을 위한 Public 처리를 마쳤다. 이제 남은 문제는 이러한 데이터를 각 Category 별로 분류를 해야한다는 것이다. 앞서 분류는 ID Settings는 Address, Age, DateOfBirth, Name, SSN, TestColor이라는 이름의 Property를 가지고 있으며, Marketting Settings는 Email과 FrequentBuyer이라는 프로퍼트를 가진다라고 하였다. 바로 여기서부터 Attribute 기법이 들어간다. Attribute 기법은 ‘[‘와 ‘]’를 통해 지정되며 클래스나 프로퍼티등에 특정한 특성(Attribute에 대한 해석은 속성이 아닌 특성으로 해야한다)을 지정하도록 하는 것이다. Category 별로 Property를 분류하기 위한 Attribute의 지시자는 CategoryAttribute이며 그 사용법은 실제 코드에 적용된 것을 살펴보면 쉽게 알 수 있을 것이다. 아래는 실제 적용되어 덧 붙여진 코드이다.

[DefaultPropertyAttribute("Name")]
public class Customer
{
    private string _name;
    private int _age;
    private DateTime _dateOfBirth;
    private string _SSN;
    private string _address;
    private string _email;
    private bool _frequentBuyer;
    private Color _color;

    public Customer() {}

    [CategoryAttribute("ID Settings"), 
    DescriptionAttribute("Name of the customer")]
    public string Name
    {
        ....
    }

    [CategoryAttribute("ID Settings"), 
    DescriptionAttribute("Color of the customer")]
    public Color TestColor
    {
        ....
    }

    [CategoryAttribute("ID Settings"),
    DescriptionAttribute("Social Security Number of the customer")]
    public string SSN
    {
        ....
    }

    [CategoryAttribute("ID Settings"),
    DescriptionAttribute("Address of the customer")]
    public string Address
    {
        ....
    }

    [CategoryAttribute("ID Settings"),
    DescriptionAttribute("Date of Birth of the Customer (optional)")]
    public DateTime DateOfBirth
    {
        ....
    }

    [CategoryAttribute("ID Settings"),
    DescriptionAttribute("Age of the customer")]
    public int Age
    {
        ....
    }

    [CategoryAttribute("Marketting Settings"),
    DescriptionAttribute("If the customer as bought more \
    than 10 times, this is set to true")]
    public bool FrequentBuyer
    {
        ....
    }

    [CategoryAttribute("Marketting Settings"),
    DescriptionAttribute("Most current e-mail of the customer")]
    public string Email
    {
        ....
    }
}

CategoryAttribute를 통해 각 Property의 Category를 지정하고 있다. CategoryAttribute 이외에 Attribute 지시자로 DescriptionAttribute와 DefaultPropertyAttribute 속성이 있는데 먼저 DefaultPropertyAttribute는 PropertyGrid가 처음 구동될때 기본적으로 선택되어질 속성을 지시하는 것이며 DescriptionAttribute는 Property를 선택했을때 PropertyGrid 컨트롤 하단의 Property의 설명에 나타날 문자열이다.

이렇게 문제의 Class를 제작했고 실제 PropertyGrid 컨트롤에 지정하는 방법은 아래와 같다. 당연이 폼상에 PropertyGrid 컨트롤을 마우스로 끌어와 넣었다는 가정에서 말이다.

private void Form1_Load(object sender, EventArgs e)
{
     Customer bill = new Customer();

    bill.Age = 50;
    bill.Address = " 114 Maple Drive ";
    bill.DateOfBirth = Convert.ToDateTime("78/9/4");
    bill.SSN = "123-345-3566";
    bill.Email = "bill@aol.com";
    bill.Name = "Bill Smith"; 
    bill.TestColor = Color.Red;

    propertyGrid1.SelectedObject = bill;
}

이제 실행해보면 애초에 원하던 결과가 나타날 것이다. 이상이 PropertyGrid의 기본적인 사용법에 대해서 살펴보았다. 다음에는 고급 사용법인 PropertyGrid에 Combo List와 사용자정의 컨트롤 등을 올리는 방법들 하나 하나를 나눠 정리해보도록 하겠다.

도움이 되었다면, 댓글이라도 하나 남겨주는 센스를 잃지 않으셨으면 합니다~ ^^*