블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2737)
Unity3D (817)
Programming (474)
Python (8)
TinyXML (5)
STL (13)
D3D (3)
MFC (1)
C/C++ (54)
C++/CLI (45)
C# (250)
WinForm (6)
WPF (5)
Math (10)
A.I. (1)
Win32API (11)
Algorithm (3)
Design Pattern (7)
UML (1)
MaxScript (1)
FMOD (4)
FX Studio (1)
Lua (2)
Terrain (1)
Shader (3)
boost (2)
Xml (2)
JSON (4)
Etc (11)
Monad (1)
Html5 (4)
Qt (1)
Houdini (0)
Regex (10)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-24 00:01

프로그래밍, C#, Web, TreeViewNode 검색, 카테고리 구현

갓 C#을 접하게된 어설픈 프로그래머 입니다. C#을 하면서 익힌 스킬을 공유하고자 합니다. 만약, 고쳐야할 부분이 있으면 알려주시면 감사하겠습니다. 

이번에 다룰 부분은 TreeView 입니다.

TreeView(트리뷰)는 가장 쉽게 얘기해서 Tistory의 카테고리를 표현하는 것처럼 그룹들을 보기 좋게 트리형태로 표현해 주는 컴포넌트입니다. 즉, 부모가 있고 부모 밑에는 자식이 있고 다시 손자가 있는 일종의 계층구조를 표시해 주는 것입니다.

Tistory의 카테고리를 표현하는 것도 일종의 TreeView 형태입니다. 당연히 C#에서 TreeView를 지원합니다. 

그럼 사용해봐야겠네요. (WebControls.TreeView 기준입니다.)

TrewView를 웹 폼에 추가를 합니다.(여기서는 이름을 trvGroup이라 명명하였습니다.)
//최상위 그룹을 생성합니다.  4Cs라고 가정합니다.
TreeNode trvNode = new TreeNode();
trvNode.Text ="4Cs";
trvNode.Value = "0";

// 4Cs라는 트리의 하부에 표현할 IT,종이접기,사는이야기 를 구성합니다.

//IT 항목 추가
TreeNode trvNodeIT = new TreeNode(); // TreeNode 인스턴스를 생성합니다. 이름은 trvNodeIT라고 하였습니다.
trvNodeIT.Text = "IT";                           // 트리뷰 상에 표시할 이름
trvNodeIT.Value = "01";                         // 구분할 값(프로그램을 내부에 사용할 값)
trvNode.ChildNodes.Add(trvNodeIT);     // 4Cs하부의 자식노드에 추가합니다.

// 종이접기 항목 추가
TreeNode trvNodeOrigami = new TreeNode();
trvNodeOrigami.Text = "종이접기";
trvNodeOrigami.Value = "02";
trvNode.ChildNodes.Add(trvNodeOrigami);

//사는이야기 항목 추가
TreeNode trvNodeLife = new TreeNode();
trvNodeLife.Text = "사는이야기";
trvNodeLife.Value = "03";
trvNode.ChildNodes.Add(trvNodeLife);

// 최종적으로 TreeView에 추가를 합니다.
trvGroup.Nodes.Add(trvNode);

위와 같이 한 후 실행을 하면 다음과 같이 표시됩니다. 

그런데 위와 같은 경우는 구조를 알고 있는 관계로 부모를 지정하고 추가를 하면 되지만 표현해야할 구조가 Database 등에서 읽어서 자동으로 표시해야할 경우는 사용할 수가 없습니다.

예로 Tistory의 개발자가 프로그램을 위와 같이 했다면, 프로그래머는 Tistory를 사용하는 블로그의 모든 구조를 확인하고 일일이 표시해야하는(?) 난감한 문제가 발생합니다.

물론, Microsoft사도 C#을 만들면서 자동으로 추가할 수 있는 무언가를 만들어 놓았겠죠. 찾아보시면 FindNode(string valuePath)라는 함수가 있습니다. 그런데 자세히 보시면 FindNode의 인자값이 valuePath라고 되어있습니다. valuePath는 TreeView에서 특정 Node가 위치한 일종의 경로를 나타냅니다. 

Default 구분자로 "/"를 사용합니다. 위의 예에서 종이접기라는 노드의 valuePath는 "부모의 value/종이접기의 value"로 구성되어 "0/02"가 됩니다. 즉, 종이접기 노드 하부에 자식 노드를 추가하기 위해서는 종이접기의 Value 뿐만 아니라 종이접기 부모의 value까지 알아야 한다는 결론입니다. 

낭패죠, FindNode를 사용하려면 미리 데이터 구조를 FindNode에 맞게 구성이 되어져야합니다.

결론은 함수를 만들어야합니다. 그것도 재귀호출함수를 만들어야 제대로 구성할 수가 있습니다. (물론, 데이터량이 많을 경우 속도에 문제가 발생할 수 있습니다.)

        // 최초 SearchNode를 호출합니다.
        // 오버로드 함수는 이름이 같으나 파라미터 등으로 구분해서 사용합니다.
        public void Disply_Tree(){
            string strParentKey;

            // 레코드에서 부모 Key를 가져옴
            strParentKey = rdr.GetInt32(0).ToString();   
            //Nodes 콜렉션과 부모 Key를 가지고 함수 호출
            TreeNode trParent = SearchNode(objTreeView.Nodes, strParantKey);  

            TreeNode trChild = new TreeNode(); 
             // 레코드에서 자신의 Key를 가져옴 (예, "02")
             trChild.Value = rdr.GetInt32(1).ToString();

             // 레코드에서 자신의 Node 이름을 가져옴 (예, "종이접기")
             trChild.Text = rdr.GetInt32(2).ToString();

             // 부모노드에 추가
             trParent.ChildNodes.Add(trChild);
        }

 //Tree 검색 - 재귀 호출 함수 (TreeView.Nodes,Key)
        public TreeNode SearchNode(TreeNodeCollection objNodes, string strKey)
        {
            // Nodes의 node를 가지고 찾을 때까지 반복합니다.
            foreach ( TreeNodnode in objNodes )
            {
                // 해당 Node를 찾을 경우 Node를 리턴합니다.
                if (node.Value == strKey) return node;

                // 없을 경우 하위 Nodes를 가지고 다시 SearchNode를 호출합니다.
                TreeNode findNode = SearchNode(node.ChildNodes,strKey);

                // 하위노드 검색 결과를 비교하여 Null이 아닐경우(찾은 경우) node를 리턴합니다.
                if ( findNode != null )
                        return findNode;
            }
            // 검색 결과 조건에 맞는 Node가 없을 경우 Null을 리턴합니다.
            return null;
        }

위와 같이 재귀함수를 통해서 아래와 같이 자동으로 트리를 구성할 수 있습니다.


프로그래밍에 도움이 되시길 바랍니다.

(알려드리지만 위의 방법은 본인의 주관적인 방법이며 만약, 다른 효과적인 방법이 있을 경우 공유해 주시면 감사하겠습니다.)

 
출처 : 
http://all4cs.tistory.com/31 
반응형
Posted by blueasa
, |
-------------------------------------------------------------------------------------------------------------------------
class PropertySettings
{
    private int index;
       
    [CategoryAttribute("Base"),
    DescriptionAttribute("인덱스 입니다."),
    DefaultValueAttribute(-1)]
    public int Index
    {
        get { return index; }
        set { index = value; }
    }
}
-------------------------------------------------------------------------------------------------------------------------
propertyGrid1.SelectedObject = PropertySettings;
-------------------------------------------------------------------------------------------------------------------------
object obj = propertyGrid1.SelectedObject;

PropertySettings settings = (PropertySettings )obj;

int index = settings.Index; 
-------------------------------------------------------------------------------------------------------------------------

이렇게 하면 되네요.
다른 더 좋은 방법 아시는 분은 알려주세요. =ㅅ=

출처 : Mine 
반응형
Posted by blueasa
, |

Sample Image - DropDownProperties.jpg

Introduction

This article discusses three types of drop down properties:

  1. Dynamic Enumeration - View a drop down combo box with dynamic values.
  2. Images & Text - Show different bitmaps based on the value in the drop down list.
  3. Drop Down Editor - Show a custom UI type editor as a drop down form.

Dynamic Enumeration

Often, we would like to show dynamic values in a combo box, avoiding hard coded values. Instead, we may load them from a database or text files to support globalization and more. In this case, the property is called Rule, and rules are loaded from the RichTextBox. First, we define an internal class, having a string array containing the list of values.

internal class HE_GlobalVars
{
    internal static string[] _ListofRules;
}

We also define a type converter as follows:

public class RuleConverter : StringConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        //true means show a combobox

        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        //true will limit to list. false will show the list, 

        //but allow free-form entry

        return true;
    }

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

The Rule property is defined as follows:

true)>
[TypeConverter(typeof(RuleConverter))]
public string Rule
{

    //When first loaded set property with the first item in the rule list.

    get {
        string S = "";
        if (_Rule != null)
        {
            S = _Rule;
        }
        else
        {
            if (HE_GlobalVars._ListofRules.Length > 0)
            {
                //Sort the list before displaying it

                Array.Sort(HE_GlobalVars._ListofRules);
                S = HE_GlobalVars._ListofRules[0];
            }
        }
        return S;
    }
    set{ _Rule = value; }
}

Then, from the application itself, we fill the list of rules:

private void UpdateListofRules()
{
    int _NumofRules = richTextBox1.Lines.Length;
    HE_GlobalVars._ListofRules = new string[_NumofRules];
    for(int i = 0; i <= _NumofRules - 1; i++)
    {
        HE_GlobalVars._ListofRules[i] = richTextBox1.Lines[i];
    }
}

Images & Text

Some property types such as ImageColor, or Font.Name paint a small representation of the value just to the left of the space where the value is shown. This is accomplished by implementing the UITypeEditor PaintValuemethod. When the property browser renders a property value for a property that defines an editor, it presents the editor with a rectangle and a Graphics object with which to paint.

Here the property named SourceType is shown as a drop down list where each value has its own image located next to it. Images are loaded from a resource file.

public enum HE_SourceType {LAN, WebPage, FTP, eMail, OCR}

public class SourceTypePropertyGridEditor : UITypeEditor
{
    public override bool GetPaintValueSupported(ITypeDescriptorContext context)
    {
        //Set to true to implement the PaintValue method

        return true;
    }

    public override void PaintValue(PaintValueEventArgs e)
    {
        //Load SampleResources file

        string m = this.GetType().Module.Name;
        m = m.Substring(0, m.Length - 4);
        ResourceManager resourceManager =
            new ResourceManager (m + ".ResourceStrings.SampleResources", 
            Assembly.GetExecutingAssembly());
        int i = (int)e.Value;
        string _SourceName = "";
        switch(i)
        {
            case ((int)HE_SourceType.LAN): _SourceName = "LANTask"; break;
            case ((int)HE_SourceType.WebPage): _SourceName = "WebTask"; break;
            case ((int)HE_SourceType.FTP): _SourceName = "FTPTask"; break;
            case ((int)HE_SourceType.eMail): _SourceName = "eMailTask"; break;
            case ((int)HE_SourceType.OCR): _SourceName = "OCRTask"; break;
        }

        //Draw the corresponding image

        Bitmap newImage = (Bitmap)resourceManager.GetObject(_SourceName);
        Rectangle destRect = e.Bounds;
        newImage.MakeTransparent();
        e.Graphics.DrawImage(newImage, destRect);
    }
}

[Editor(typeof(SourceTypePropertyGridEditor), 
        typeof(System.Drawing.Design.UITypeEditor))]
public HE_SourceType SourceType
{
    get{return _SourceType;}
    set{_SourceType = value;}
}

Drop Down Editor

Visual Studio .NET uses type converters for text-based property editing and code serialization. Some built-in types, such as Color or DockStyle, get a specialized user interface in the property grid as well as text support. If you would like to supply a graphical editing interface for your own property types, you can do so by supplying a UI type editor as a drop-down editor user interface.

First, we create a form to be used as an editor. When initializing the form, we must set its TopLevel property tofalse. To make it caption-less, we have to set the following properties:

this.MaximizeBox = false;
this.MinimizeBox = false;
this.ControlBox = false;
this.ShowInTaskbar = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

The Contrast property is used in this case.

The following code uses the IServiceProvider passed to EditValue. It asks it for theIWindowsFormsEditorService interface (which is defined in the System.Windows.Forms.Designnamespace). This service provides the facility for opening a drop-down editor, we simply call the DropDownControlmethod on it, and it will open whichever control we pass. It sets the size and location of the control so that it appears directly below the property when the drop-down arrow is clicked.

When we write the UI editor class itself, we have a choice as to the kind of user interface we can supply. We can either open a modal dialog or supply a pop-up user interface that will appear in the property grid itself. We indicate this by overriding the GetEditStyle method. This method returns a value from the UITypeEditorEditStyleenumeration, either Modal or DropDown. For either type of user interface, we must also override the EditValuemethod, which will be called when the user tries to edit the value. The value returned from EditValue will be written back to the property. It will call EditValue when the arrow button is clicked.

public class ContrastEditor : 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)
        {
            frmContrast _frmContrast = new frmContrast();
            _frmContrast.trackBar1.Value = (int) value;
            _frmContrast.BarValue = _frmContrast.trackBar1.Value;
            _frmContrast._wfes = wfes;

            wfes.DropDownControl(_frmContrast);
            value = _frmContrast.BarValue;
        }
        return value;
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


출처 :
 http://www.codeproject.com/KB/cpp/dropdownproperties.aspx

반응형
Posted by blueasa
, |

form.TopLevel = false;
로 해주면 됩니다.

말 그대로 컨트롤에 최상위(Top) 컨트롤을 넣을 수 없어서 생기는 문제네요..

참조 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNO=8&no=115184&ref=115179
반응형
Posted by blueasa
, |

표준 Dispose 패턴

Programming/C# / 2011. 10. 31. 11:11

public class MyResourceHog :IDisposable
{
//이미dispose되었는지의 여부를 저장하기 위한 플래그
private bool _alreadyDisposed = false;

//finalizer
//virtual Dispose 메서드를 호출한다.
~MyResourceHog()
{
Dispose(false);
}

//IDisposable Interface의 구현
//virtual Dispose메서드를 호출하고
//Finalization이 수행되지 않도록한다.
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(true);
}

//virtual Dispose 메서드
protected virtual void Dispose(bool isDisposing)
{
//여려번 dispose를 수행하지 않도록 한다.
if (_alreadyDisposed)
return;
if (isDisposing)
{
//해야할 일: managed 리소스를 해제한다.
}

//해야할 일:unmanaged 리소스를 해제한다.
//dispose 플래그를 설정한다.
_alreadyDispose = true;
}
}

public class DerivedResourceHog : MyResourceHog
{
private bool _disposed = false;

protected override void Dispose(bool isDisposing)
{
//여러번dispose를 수행하지 않도록 한다.
if(_disposde)
return;
if(isDisposing)
{
//해야할일: managed 리소스를 해제한다.
}
// 해야할일: unmanaged 리소스를 해제한다.

//기반 class가 자신의 리소스를 해제할 수 있도록 한다.
//기반 class는
//GC.SuppressFinalize()를 호출할 책임이 있다.
base.Dispose(isDisposing);
//하위class의 dispose 플래그를 설정한다.
_dispose = true;
}
}

[출처] 표준 Dispose 패턴|작성자 joose2

반응형
Posted by blueasa
, |

As with many other technologies, the design time experience in Windows Workflow Foundation uses many of the same extensibility mechanisms found in other designers (such as the Windows Forms designer). One of those is the hability to provide custom type editors for properties by creating an UITypeEditor-derived class and then associating it with the property via the [Editor] attribute.

Here's a sample UITypeEditor that will present an OpenFileDialog to choose a file name as the property value:

//
// FileSelectorTypeEditor.cs
//
// Author:
//    Tomas Restrepo (tomasr@mvps.org)
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace Winterdom.Design.TypeEditors
{
   /// <summary>
   /// Customer UITypeEditor that pops up a
   /// file selector dialog
   /// </summary>
   public class FileSelectorTypeEditor : UITypeEditor
   {
      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
         if ( context == null || context.Instance == null )
            return base.GetEditStyle(context);
         return UITypeEditorEditStyle.Modal;
      }

      public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
         IWindowsFormsEditorService editorService;

         if ( context == null || context.Instance == null || provider == null )
            return value;

         try
         {
            // get the editor service, just like in windows forms
            editorService = (IWindowsFormsEditorService)
               provider.GetService(typeof(IWindowsFormsEditorService));

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files (*.*)|*.*";
            dlg.CheckFileExists = true;

            string filename = (string)value;
            if ( !File.Exists(filename) )
               filename = null;
            dlg.FileName = filename;

            using ( dlg )
            {
               DialogResult res = dlg.ShowDialog();
               if ( res == DialogResult.OK )
               {
                  filename = dlg.FileName;
               }
            }
            return filename;

         } finally
         {
            editorService = null;
         }
      }
   } // class FileSelectorTypeEditor

} // namespace Winterdom.Design.TypeEditors

You can then easily associate it with a property like this:

[Editor(typeof(FileSelectorTypeEditor), typeof(UITypeEditor))]
public string Filename
{
   get { return _filename; }
   set { _filename = value; }
}

One thing to watch out for, though, is that at least with the July CTP of WinFX, WF will completely ignore your custom UITypeEditor if it is defined in the same assembly as the activity using it. Don't know why, but make sure you define it in a separate assembly you reference, and it should work OK.


출처 : http://winterdom.com/2006/08/acustomuitypeeditorforactivityproperties

반응형
Posted by blueasa
, |
반응형

'Programming > C#' 카테고리의 다른 글

표준 Dispose 패턴  (0) 2011.10.31
PropertyGrid Attribute FileSelectorTypeEditor  (0) 2011.10.27
PropertyGrid 컨트롤 최대 활용  (0) 2011.10.26
ContextMenuStrip Item 동적 제어  (0) 2011.10.26
Windows Forms FAQ  (0) 2011.10.25
Posted by blueasa
, |


요약 : Microsoft .NET Framework의 PropertyGrid 컨트롤과 이 컨트롤을 응용 프로그램에 맞게 설정하는 방법을 이해할 수 있도록 도와줍니다(37페이지/인쇄 페이지 기준).

적용 대상:
   Microsoft .NET Framework
   Microsoft Visual Studio .NET

목차

PropertyGrid 컨트롤 소개  PropertyGrid 컨트롤 소개 
PropertyGrid 컨트롤 만들기  PropertyGrid 컨트롤 만들기 
PropertyGrid 컨트롤을 사용할 위치  PropertyGrid 컨트롤을 사용할 위치 
개체 선택 개체 선택 
사용자에 맞게 PropertyGrid 컨트롤 지정  사용자에 맞게 PropertyGrid 컨트롤 지정 
복잡한 속성 표시 복잡한 속성 표시 
속성에 대한 사용자 지정 UI 제공 속성에 대한 사용자 지정 UI 제공 
결론  결론 

PropertyGrid 컨트롤 소개

Microsoft Visual Basic 또는 Microsoft Visual Studio .NET을 사용한다면 속성 브라우저를 사용하여 하나 이상의 개체 속성을 찾아보기, 보기 및 편집했습니다. Visual Studio .NET에 있는 속성 브라우저의 핵심은 .NET FrameworkPropertyGrid 컨트롤입니다. PropertyGrid 컨트롤은 개체 또는 형식의 속성을 표시하고, 주로 리플렉션을 사용하여 항목의 속성을 검색합니다. 리플렉션은 런타임에 형식 정보를 제공하는 기술입니다.

다음 스크린 샷에서는 PropertyGrid를 폼에 배치했을 때의 모양을 보여줍니다.

그림

그림 1. 폼의 PropertyGrid

PropertyGrid에는 다음과 같은 부분이 포함되어 있습니다.

  • 속성

  • 확장 가능한 속성

  • 속성 범주 제목

  • 속성 설명

  • 속성 편집기

  • 속성 탭

  • 명령 창(컨트롤의 디자이너가 노출하는 디자이너 동사를 표시함)

PropertyGrid 컨트롤 만들기

Visual Studio .NET을 사용하여 PropertyGrid 컨트롤을 만들려면 PropertyGrid 컨트롤을 도구 상자에 추가해야 합니다. 이 컨트롤은 기본적으로 도구 상자에 포함되어 있지 않습니다. 도구 메뉴에서 도구 상자 사용자 지정을 선택합니다. 대화 상자에서 Framework 구성 요소 탭을 선택한 다음 PropertyGrid를 선택합니다.

명령줄에서 코드를 컴파일할 경우 /reference 옵션을 사용하고 System.Windows.Forms.dll을 지정합니다.

다음 코드에서는 PropertyGrid 컨트롤을 만들어 폼에 추가하는 방법을 설명합니다.

' Visual Basic
 
Imports System
Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Globalization
 
Public Class OptionsDialog
   Inherits System.Windows.Forms.Form
 
   Private OptionsPropertyGrid As System.Windows.Forms.PropertyGrid
 
   Public Sub New()
      MyBase.New()
 
      OptionsPropertyGrid = New PropertyGrid()
      OptionsPropertyGrid.Size = New Size(300, 250)
 
      Me.Controls.Add(OptionsPropertyGrid)
      Me.Text = "옵션 대화 상자"
   End Sub
End Class
 
 
//C#
 
using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using System.Globalization;
 
public class OptionsDialog : System.Windows.Forms.Form
{
   private System.Windows.Forms.PropertyGrid OptionsPropertyGrid;
   public OptionsDialog()
   {
      OptionsPropertyGrid = new PropertyGrid();
      OptionsPropertyGrid.Size = new Size(300, 250);
 
      this.Controls.Add(OptionsPropertyGrid);
      this.Text = "옵션 대화 상자";
   }
 
   [STAThread]
   static void Main() 
   {
      Application.Run(new OptionsDialog());
   }
}

PropertyGrid 컨트롤을 사용할 위치

응용 프로그램에는 사용자가 PropertyGrid와 상호 작용하여 풍부한 편집을 경험할 수 있는 장소가 많이 있습니다. 한 가지 예로 사용자가 설정할 수 있는 여러 "설정"이나 옵션이 있는 응용 프로그램을 들 수 있습니다. 이러한 "설정"이나 옵션 중 일부는 복잡합니다. 라디오 단추, 콤보 상자 또는 텍스트 상자를 사용하여 이런 옵션을 나타낼 수 있습니다. 이 문서에서는 PropertyGrid 컨트롤을 사용하여 응용 프로그램 옵션을 설정하기 위한 옵션 창을 만드는 과정을 안내합니다. 위에서 만든 OptionsDialog 폼이 옵션 창의 시작이 됩니다. 이제 응용 프로그램 설정에 매핑되는 모든 속성이 포함된 AppSettings라는 클래스를 만듭니다. 개별 변수를 사용하는 대신 별도의 클래스를 만들 경우 설정을 훨씬 더 쉽게 유지 관리할 수 있습니다.

' Visual Basic
 
Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "응용 프로그램을 시작합니다."
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4
 
    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"
 
    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property
 
    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property
 
    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property
 
    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property
 
    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property
 
    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class
 
 
//C#
 
public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "응용 프로그램을 시작합니다.";
    private int itemsInMRU = 4;
    private int maxRepeatRate = 10;
    private bool settingsChanged = false;
    private string appVersion = "1.0";
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

옵션 창의 PropertyGrid에서 이 클래스를 조작하므로, 폼의 소스 코드 아래쪽이나 새 파일에 응용 프로그램 프로젝트에 대한 클래스 정의를 추가합니다.

개체 선택

PropertyGrid에서 표시하는 내용을 확인하려면 PropertyGrid.SelectedObject 속성을 개체 인스턴스로 설정합니다.PropertyGrid에서 나머지 작업을 실행합니다. SelectedObject를 설정할 때마다 PropertyGrid에서 표시된 속성을 새로 고칩니다. 그렇게 하면 속성 새로 고침이나 런타임에서 개체 간 전환을 쉽게 실행할 수 있습니다.PropertyGrid.Refresh 메서드를 호출하여 속성을 새로 고칠 수도 있습니다.

계속하려면 OptionsDialog 생성자의 코드를 업데이트하여 AppSettings 개체를 만들어 PropertyGrid.SelectedObject속성으로 설정합니다.

' Visual Basic
 
   Public Sub New()
      MyBase.New()
 
      OptionsPropertyGrid = New PropertyGrid()
      OptionsPropertyGrid.Size = New Size(300, 250)
 
      Me.Controls.Add(OptionsPropertyGrid)
      Me.Text = "옵션 대화 상자"
 
      ' AppSettings 클래스를 만들어 PropertyGrid에 표시합니다.  
      Dim appset as AppSettings = New AppSettings()
      OptionsPropertyGrid.SelectedObject = appset
   End Sub
 
 
//C#
 
   public OptionsDialog()
   {
      OptionsPropertyGrid = new PropertyGrid();
      OptionsPropertyGrid.Size = new Size(300, 250);
 
      this.Controls.Add(OptionsPropertyGrid);
      this.Text = "옵션 대화 상자";
 
      // AppSettings 클래스를 만들어 PropertyGrid에 표시합니다.  
      AppSettings appset = new AppSettings();
      OptionsPropertyGrid.SelectedObject = appset;
   }

응용 프로그램을 컴파일하고 실행합니다. 다음 스크린 샷에서는 그 모양을 보여줍니다.

그림

그림 2. PropertyGrid 에서   선택한 AppSettings 클래스

사용자에 맞게 PropertyGrid 컨트롤 지정

필요에 따라 PropertyGrid의 시각적인 모양을 일부 수정할 수 있습니다. 일부 속성이 표시되는 방법을 변경하거나, 일부 속성이 표시되지 않도록 선택할 수도 있습니다. PropertyGrid를 사용자에 맞게 설정하려면 어떻게 합니까

PropertyGrid의 시각적인 모양 변경

PropertyGrid의 많은 시각적인 모양을 사용자에 맞게 설정할 수 있습니다. 몇 가지 예를 들면 다음과 같습니다.

  • HelpBackColorHelpForeColor 또는 HelpVisible 속성을 통해 배경색을 변경하거나, 글꼴 색을 변경하거나, 설명 창을 숨깁니다.

  • ToolbarVisible 속성을 통해 도구 모음을 숨기고, BackColor 속성을 통해 도구 모음의 색을 변경하고,LargeButtons 속성을 통해 큰 도구 모음 단추를 표시합니다.

  • PropertySort 속성을 사용하여 속성을 사전순으로 정렬하고 항목별로 정렬합니다.

  • BackColor 속성을 통해 분할자 색을 변경합니다.

  • LineColor 속성을 통해 모눈선과 테두리를 변경합니다.

    이 예제의 옵션 창의 경우 도구 모음이 필요하지 않기 때문에 ToolbarVisible을 false로 설정합니다. 다른 기본 설정을 유지합니다.

속성 표시 방법 변경

일부 속성이 표시되는 방법을 변경하기 위해 속성에 다른 특성을 적용할 수 있습니다. 특성은 리플렉션을 사용하여 런타임에서 검색할 수 있는 형식, 필드, 메서드, 속성 등과 같은 프로그래밍 요소에 주석을 다는 데 사용되는 선언 태그입니다. 몇 가지 예를 들면 다음과 같습니다.

  • DescriptionAttribute – 속성 아래 있는 설명 도움말 창에 표시되는 속성에 대한 텍스트를 설정합니다. 포커스가 있는 속성인 활성 속성에 대한 도움말 텍스트를 제공할 수 있는 유용한 방법입니다. 이 특성을 MaxRepeatRate 속성에 적용합니다.

  • CategoryAttribute – 표에서 속성이 속하는 범주를 설정합니다. 속성을 범주 이름별로 그룹화할 경우에 유용합니다. 속성에 범주를 지정하지 않으면 Misc 범주가 할당됩니다. 이 특성을 모든 속성에 적용합니다.

  • BrowsableAttribute – 속성이 표에 표시되는지 여부를 나타냅니다. 표에서 속성을 숨기고자 할 경우에 유용합니다. 기본적으로 공개 속성은 항상 표에 표시됩니다. 이 특성을 SettingsChanged 속성에 적용합니다.

  • ReadOnlyAttribute – 속성이 읽기 전용인지 여부를 나타냅니다. 표에서 속성을 편집할 수 없게 할 경우에 유용합니다. 기본적으로 get 및 set 접근자 함수가 있는 공개 속성은 표에서 편집할 수 있습니다. 이 특성을 AppVersion 속성에 적용합니다.

  • DefaultValueAttribute – 속성의 기본값을 식별합니다. 속성에 대한 기본값을 제공하고 나중에 속성 값이 기본값과 다른지 확인할 때 유용합니다. 이 특성을 모든 속성에 적용합니다.

  • DefaultPropertyAttribute – 클래스의 기본 속성을 식별합니다. 클래스의 기본 속성은 표에서 클래스를 처음 선택할 때 포커스를 가집니다. 이 특성을 AppSettings 클래스에 적용합니다.

이제 이 특성 중 일부를 AppSettings 클래스에 적용하여 PropertyGrid에 속성이 표시되는 방법을 변경합니다.

' Visual Basic
 
<DefaultPropertyAttribute("SaveOnClose")> _
Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "응용 프로그램을 시작합니다."
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4
 
    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"
 
    <CategoryAttribute("문서 설정"), _
     DefaultValueAttribute(True)> _
    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property
 
    <CategoryAttribute("전역 설정"), _
    ReadOnlyAttribute(True), _
    DefaultValueAttribute("응용 프로그램을 시작합니다.")> _
    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property
 
    <CategoryAttribute("전역 설정"), _
    DefaultValueAttribute(4)> _
    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property
 
    <DescriptionAttribute("텍스트가 반복되는 속도(밀리초)"), _
    CategoryAttribute("전역 설정"), _
    DefaultValueAttribute(10)> _
    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property
 
    <BrowsableAttribute(False),
     DefaultValueAttribute(False)> _
    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property
 
    <CategoryAttribute("버전"), _
    DefaultValueAttribute("1.0"), _
    ReadOnlyAttribute(True)> _
    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class
 
 
//C#
[DefaultPropertyAttribute("SaveOnClose")]
public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "응용 프로그램을 시작합니다.";
    private int maxRepeatRate = 10;
    private int itemsInMRU = 4;
 
    private bool settingsChanged = false;
    private string appVersion = "1.0";
 
    [CategoryAttribute("문서 설정"),
    DefaultValueAttribute(true)]
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }
 
    [CategoryAttribute("전역 설정"),
    ReadOnlyAttribute(true),
    DefaultValueAttribute("응용 프로그램을 시작합니다.")] 
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }
 
    [CategoryAttribute("전역 설정"),
    DefaultValueAttribute(4)]
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }
 
    [DescriptionAttribute("텍스트가 반복되는 속도(밀리초)"),
    CategoryAttribute("전역 설정"),
    DefaultValueAttribute(10)]
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }
 
    [BrowsableAttribute(false),
    DefaultValueAttribute(false)]
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }
 
    [CategoryAttribute("버전"),
    DefaultValueAttribute("1.0"),
    ReadOnlyAttribute(true)]
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

이 특성들을 AppSettings 클래스에 적용하여 응용 프로그램을 컴파일하고 실행합니다. 다음 스크린 샷에서는 그 모양을 보여줍니다.

그림

그림 3. PropertyGrid    범주      기본값과   함께   표시되는   속성  

이 버전의 옵션 창에서 작업한 후 다음이 표시될 수 있습니다.

  • 창이 표시될 때 SaveOnClose 속성이 포커스를 가집니다.

  • MaxRepeatRate 속성을 선택하면 설명 도움말 창에 "텍스트가 반복되는 속도(밀리초)"가 표시됩니다.

  • SaveOnClose 속성은 "문서 설정" 범주 아래에 표시됩니다. 다른 속성들은 "전역 설정"과 "버전"이라는 다른 두 범주 아래에 표시됩니다.

  • SettingsChanged 속성은 더 이상 표시되지 않습니다.

  • AppVersion 속성은 읽기 전용입니다. 읽기 전용 속성은 희미한 텍스트로 표시됩니다.

  • SaveOnClose 속성에 true 이외의 다른 값이 있을 경우 굵은 텍스트로 표시됩니다. PropertyGrid에서는 굵은 텍스트를 사용하여 기본값이 아닌 값을 갖는 속성을 나타냅니다.

복잡한 속성 표시

지금까지는 옵션 창에 정수, 부울, 문자열 등과 같은 간단한 형식을 표시했습니다. 복잡한 형식은 어떻게 합니까 응용 프로그램에서 창 크기, 문서 글꼴, 도구 모음 색 등을 추적해야 할 경우에는 어떻게 합니까 .NET Framework에서 제공하는 일부 데이터 형식에는 PropertyGrid에서 사용할 수 있게 도와주는 특수한 표시 기능이 있습니다.

제공된 형식 지원

먼저 AppSettings 클래스를 업데이트하여 창 크기(Size 형식), 창 글꼴(Font 형식) 및 도구 모음 색(Color 형식)에 대한 새로운 속성을 추가합니다.

' Visual Basic
 
<DefaultPropertyAttribute("SaveOnClose")> _
Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "응용 프로그램을 시작합니다."
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4
 
    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"
 
    Private _windowSize As Size = New Size(100, 100)
    Private _windowFont As Font = New Font("굴림", 8, FontStyle.Regular)
    Private _toolbarColor As Color = SystemColors.Control
 
    <CategoryAttribute("문서 설정"), _
     DefaultValueAttribute(True)> _
    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property
 
    <CategoryAttribute("문서 설정")> _
    Public Property WindowSize() As Size
        Get
            Return _windowSize
        End Get
        Set(ByVal Value As Size)
            _windowSize = Value
        End Set
    End Property
 
    <CategoryAttribute("문서 설정")> _
    Public Property WindowFont() As Font
        Get
            Return _windowFont
        End Get
        Set(ByVal Value As Font)
            _windowFont = Value
        End Set
    End Property
 
    <CategoryAttribute("전역 설정")> _
    Public Property ToolbarColor() As Color
        Get
            Return _toolbarColor
        End Get
        Set(ByVal Value As Color)
            _toolbarColor = Value
        End Set
    End Property
 
    <CategoryAttribute("전역 설정"), _
    ReadOnlyAttribute(True), _
    DefaultValueAttribute("응용 프로그램을 시작합니다.")> _
    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property
 
    <CategoryAttribute("전역 설정"), _
    DefaultValueAttribute(4)> _
    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property
 
    <DescriptionAttribute("텍스트가 반복되는 속도(밀리초)"), _
    CategoryAttribute("전역 설정"), _
    DefaultValueAttribute(10)> _
    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property
 
    <BrowsableAttribute(False),
     DefaultValueAttribute(False)> _
    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property
 
    <CategoryAttribute("버전"), _
    DefaultValueAttribute("1.0"), _
    ReadOnlyAttribute(True)> _
    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class
 
 
//C#
 
[DefaultPropertyAttribute("SaveOnClose")]
public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "응용 프로그램을 시작합니다.";
    private int maxRepeatRate = 10;
    private int itemsInMRU = 4;
 
    private bool settingsChanged = false;
    private string appVersion = "1.0";
 
    private Size windowSize = new Size(100,100);
    private Font windowFont = new Font("굴림", 8, FontStyle.Regular);
    private Color toolbarColor = SystemColors.Control;
 
    [CategoryAttribute("문서 설정"),
    DefaultValueAttribute(true)]
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }
 
    [CategoryAttribute("문서 설정")]
    public Size WindowSize 
    {
        get { return windowSize; }
        set { windowSize = value;}
 
   }
 
    [CategoryAttribute("문서 설정")]
    public Font WindowFont 
    {
        get {return windowFont; }
        set { windowFont = value;}
 
   }
 
    [CategoryAttribute("전역 설정")]
    public Color ToolbarColor
    {
        get { return toolbarColor; }
        set { toolbarColor = value; }
 
   }
 
    [CategoryAttribute("전역 설정"),
    ReadOnlyAttribute(true),
    DefaultValueAttribute("응용 프로그램을 시작합니다.")]
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }
 
    [CategoryAttribute("전역 설정"),
    DefaultValueAttribute(4)]
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }
 
    [DescriptionAttribute("텍스트가 반복되는 속도(밀리초)"),
    CategoryAttribute("전역 설정"),
    DefaultValueAttribute(10)]
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }
 
    [BrowsableAttribute(false),
    DefaultValueAttribute(false)]
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }
 
    [CategoryAttribute("버전"),
    DefaultValueAttribute("1.0"),
    ReadOnlyAttribute(true)]
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

다음 스크린 샷에서는 새 속성이 PropertyGrid에 표시되는 모양을 보여줍니다.

그림

그림 4. PropertyGrid    표시되는 .NET Framework 데이터   형식

WindowFont 속성에는 누르면 글꼴 선택 대화 상자가 표시되는 줄임표("...") 단추가 있습니다. 이 속성을 확장하여 더 많은 Font 속성을 표시할 수 있습니다. Font 속성 중 일부에는 글꼴에 대한 정보와 값의 드롭다운 목록이 제공됩니다. WindowSize 속성을 확장하여 더 많은 Size 형식 속성을 표시할 수 있습니다. 마지막으로 ToolbarColor 속성에는 선택한 색의 견본과 다른 색을 선택하기 위한 사용자 지정 드롭다운 목록이 있습니다. 모든 데이터 형식에 대해 .NET Framework는 PropertyGrid에서 보다 쉽게 편집할 수 있도록 추가 클래스를 제공합니다.

사용자 지정 형식 지원

이제 두 AppSettings 클래스에 DefaultFileName 및 SpellCheckOptions라는 두 클래스를 추가합니다. DefaultFileName 속성은 문자열을 가져오거나 설정하고 SpellCheckOptions 속성은 SpellingOptions 클래스의 인스턴스를 가져오거나 설정합니다.

SpellingOptions 클래스는 응용 프로그램의 맞춤법 검사 속성을 관리하는 새 클래스입니다. 개체의 속성을 관리하는 별도의 클래스를 만들 경우에 대한 정확한 규칙은 없으며, 전체적인 클래스 디자인을 기준으로 합니다. 폼의 소스 코드 아래쪽이나 새 파일에 SpellingOptions 클래스에 대한 정의를 추가합니다.

Visual Basic
 
<DescriptionAttribute("응용 프로그램의 맞춤법 검사 옵션이 표시되도록 확장합니다.")> _
Public Class SpellingOptions
    Private _spellCheckWhileTyping As Boolean = True
    Private _spellCheckCAPS As Boolean = False
    Private _suggestCorrections As Boolean = True
 
    <DefaultValueAttribute(True)> _
    Public Property SpellCheckWhileTyping() As Boolean
        Get
            Return _spellCheckWhileTyping
        End Get
        Set(ByVal Value As Boolean)
            _spellCheckWhileTyping = Value
        End Set
    End Property
 
    <DefaultValueAttribute(False)> _
    Public Property SpellCheckCAPS() As Boolean
        Get
            Return _spellCheckCAPS
        End Get
        Set(ByVal Value As Boolean)
            _spellCheckCAPS = Value
        End Set
    End Property
 
    <DefaultValueAttribute(True)> _
    Public Property SuggestCorrections() As Boolean
        Get
            Return _suggestCorrections
        End Get
        Set(ByVal Value As Boolean)
            _suggestCorrections = Value
        End Set
    End Property
End Class
 
 
//C#
 
[DescriptionAttribute("응용 프로그램의 맞춤법 검사 옵션이 표시되도록 확장합니다.")]
public class SpellingOptions{
    private bool spellCheckWhileTyping = true;
    private bool spellCheckCAPS = false;
    private bool suggestCorrections = true;
 
    [DefaultValueAttribute(true)]
    public bool SpellCheckWhileTyping 
    {
        get { return spellCheckWhileTyping; }
        set { spellCheckWhileTyping = value; }
    }
 
    [DefaultValueAttribute(false)]
    public bool SpellCheckCAPS 
    {
        get { return spellCheckCAPS; }
        set { spellCheckCAPS = value; }
    }
    [DefaultValueAttribute(true)]
    public bool SuggestCorrections 
    {
        get { return suggestCorrections; }
        set { suggestCorrections = value; }
    }
}

옵션 창 응용 프로그램을 다시 컴파일하고 실행합니다. 다음 스크린 샷에서는 그 모양을 보여줍니다.

그림

그림 5. PropertyGrid    표시되는   형식   변환기   없는   사용자   지정   데이터   형식

SpellcheckOptions 속성의 모양을 주의하십시오. .NET Framework 형식과 달리 이 사용자 지정 데이터 형식은 사용자 지정 문자열 표현을 확장하거나 표시하지 않습니다. .NET Framework 형식에서 사용자의 복잡한 형식을 편집할 때와 동일한 경험을 하려면 어떻게 합니까 .NET Framework 형식에서는 TypeConverter 및 UITypeEditor 클래스를 사용하여 PropertyGrid 편집을 대부분 지원하며, 사용자도 두 클래스를 사용할 수 있습니다.

확장 가능한 속성 지원 추가

PropertyGrid를 가져와서 SpellingOptions 속성을 확장하려면 TypeConverter를 만들어야 합니다. TypeConverter는 형식을 변환할 수 있는 방법을 제공합니다. PropertyGrid는 TypeConverter를 사용하여 개체 형식을 개체 값을 표 모양으로 표시하는 데 사용하는 String으로 변환합니다. 편집하는 동안 TypeConverter는 String에서 사용자 개체 형식으로 다시 변환합니다. .NET Framework에는 이 과정을 더 쉽게 해주는 ExpandableObjectConverter 클래스가 제공됩니다.

확장 가능한 개체 지원을 제공하려면
  1. ExpandableObjectConverter에서 상속되는 클래스를 만듭니다.

    ' Visual Basic
     
    Public Class SpellingOptionsConverter
        Inherits ExpandableObjectConverter
    End Class
     
     
    //C#
     
    public class SpellingOptionsConverter:ExpandableObjectConverter 
    {  }
  2. CanConvertTo 메서드를 재정의하고 destinationType 매개 변수가 이 형식 변환기(사용자 예제의 SpellingOptions 클래스)를 사용하는 클래스와 같은 형식일 경우 true를 반환합니다. 그렇지 않으면 기본 클래스CanConvertTo 메서드의 값을 반환합니다.

    ' Visual Basic
     
    Public Overloads Overrides Function CanConvertTo( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal destinationType As Type) As Boolean
        If (destinationType Is GetType(SpellingOptions)) Then
            Return True
        End If
        Return MyBase.CanConvertTo(context, destinationType)
    End Function
    

                    

    //C#   public override bool CanConvertTo(ITypeDescriptorContext context,                                   System.Type destinationType) {     if (destinationType == typeof(SpellingOptions))         return true;       return base.CanConvertTo(context, destinationType); }

  3. ConvertTo 메서드를 재정의하고 destinationType 매개 변수가 String이고 값이 이 형식 변환기(사용자 예제의 SpellingOptions 클래스)를 사용하는 클래스와 같은 형식인지 확인합니다. 두 경우 중 하나라도 false이면 기본 클래스 ConvertTo 메서드의 값을 반환하고, 그렇지 않으면 값 개체의 문자열 표현을 반환합니다. 문자열 표현에서는 클래스의 각 속성을 고유 구분 기호로 구분해야 합니다. 전체 문자열이 PropertyGrid에 표시되기 때문에 읽는 데 방해가 되지 않는 구분 기호를 선택하는 것이 좋습니다. 대개 쉼표가 적당합니다.

    ' Visual Basic
     
    Public Overloads Overrides Function ConvertTo( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal culture As CultureInfo, _
                                  ByVal value As Object, _
                                  ByVal destinationType As System.Type) _
                         As Object
        If (destinationType Is GetType(System.String) _
            AndAlso TypeOf value Is SpellingOptions) Then
     
            Dim so As SpellingOptions = CType(value, SpellingOptions)
     
            Return "입력하는 동안 검사: " & so.SpellCheckWhileTyping & _
                   ", CAPS 검사: " & so.SpellCheckCAPS & _
                   ", 단어 추천: " & so.SuggestCorrections
        End If
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function
    

    //C#
     
    public override object ConvertTo(ITypeDescriptorContext context,
                                   CultureInfo culture, 
                                   object value, 
                                   System.Type destinationType) 
    {
        if (destinationType == typeof(System.String) && 
             value is SpellingOptions){
     
            SpellingOptions so = (SpellingOptions)value;
     
            return "입력하는 동안 검사:" + so.SpellCheckWhileTyping + 
                   ", CAPS 검사: " + so.SpellCheckCAPS +
                   ", 단어 추천: " + so.SuggestCorrections;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
  4. (옵션) 형식 변환기가 문자열에서 변환할 수 있게 지정하면 표의 개체 문자열 표현을 편집할 수 있습니다. 이렇게 하려면 먼저 CanConvertFrom 메서드를 재정의하고 소스 Type 매개 변수가 String 형식일 경우 true를 반환하고, 그렇지 않으면 기본 클래스 CanConvertFrom 메서드의 값을 반환합니다.

    ' Visual Basic
     
    Public Overloads Overrides Function CanConvertFrom( _
                               ByVal context As ITypeDescriptorContext, _
                               ByVal sourceType As System.Type) As Boolean
        If (sourceType Is GetType(String)) Then
            Return True
        End If
        Return MyBase.CanConvertFrom(context, sourceType)
    End Function
    

    //C#
     
    public override bool CanConvertFrom(ITypeDescriptorContext context,
                                  System.Type sourceType) 
    {
        if (sourceType == typeof(string))
            return true;
     
        return base.CanConvertFrom(context, sourceType);
    }
  5. 개체의 기본 클래스를 편집할 수 있게 하려면 ConvertFrom 메서드를 재정의하고 값 매개 변수가 String인지 확인합니다. 값 매개 변수가 String이 아니면 기본 클래스 ConvertFrom 메서드의 값을 반환하고, 그렇지 않으면 값 매개 변수를 기반으로 클래스(사용자 예제의 SpellingOptions 클래스)의 새 인스턴스를 반환합니다. 값 매개 변수에서 클래스의 각 속성에 대한 값을 구문 분석해야 합니다. ConvertTo 메서드에서 만든 구분 문자열의 형식을 알고 있으면 구문 분석을 실행하는 데 도움이 됩니다.

    ' Visual Basic
     
    Public Overloads Overrides Function ConvertFrom( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal culture As CultureInfo, _
                                  ByVal value As Object) As Object
     
        If (TypeOf value Is String) Then
            Try
                Dim s As String = CStr(value)
                Dim colon As Integer = s.IndexOf(":")
                Dim comma As Integer = s.IndexOf(",")
     
                If (colon <> -1 AndAlso comma <> -1) Then
                    Dim checkWhileTyping As String = s.Substring(colon + 1, _
                                                    (comma - colon - 1))
     
                    colon = s.IndexOf(":", comma + 1)
                    comma = s.IndexOf(",", comma + 1)
     
                    Dim checkCaps As String = s.Substring(colon + 1, _
                                                    (comma - colon - 1))
     
                    colon = s.IndexOf(":", comma + 1)
     
                    Dim suggCorr As String = s.Substring(colon + 1)
     
                    Dim so As SpellingOptions = New SpellingOptions()
     
                    so.SpellCheckWhileTyping = Boolean.Parse(checkWhileTyping)
                    so.SpellCheckCAPS = Boolean.Parse(checkCaps)
                    so.SuggestCorrections = Boolean.Parse(suggCorr)
     
                    Return so
                End If
            Catch
                Throw New ArgumentException( _
                    "& CStr(value) & _을" 
                                    "SpellingOptions 형식으로" "변환할 수 없습니다")
     
            End Try
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function
    

    //C#
     
    public override object ConvertFrom(ITypeDescriptorContext context,
                                  CultureInfo culture, object value) 
    {
        if (value is string) {
            try {
                string s = (string) value;
                int colon = s.IndexOf(':');
                int comma = s.IndexOf(',');
     
                if (colon != -1 && comma != -1) {
                    string checkWhileTyping = s.Substring(colon + 1 ,
                                                    (comma - colon - 1));
     
                    colon = s.IndexOf(':', comma + 1);
                    comma = s.IndexOf(',', comma + 1);
     
                    string checkCaps = s.Substring(colon + 1 , 
                                                    (comma - colon -1));
     
                    colon = s.IndexOf(':', comma + 1);
     
                    string suggCorr = s.Substring(colon + 1);
     
                    SpellingOptions so = new SpellingOptions();
     
                    so.SpellCheckWhileTyping =Boolean.Parse(checkWhileTyping);
                    so.SpellCheckCAPS = Boolean.Parse(checkCaps);
                    so.SuggestCorrections = Boolean.Parse(suggCorr);
                    return so;
                }
            }
            catch {
                throw new ArgumentException(
                    "+ (string)value +를" 
                                       "SpellingOptions 형식으로" "변환할 수 없습니다");
            }
        }  
        return base.ConvertFrom(context, culture, value);
    }
  6. 이제 형식 변환기 클래스가 만들어 졌으므로 이 형식 변환기 클래스를 사용할 대상 클래스를 식별해야 합니다.TypeConverterAttribute를 대상 클래스(사용자 예제의 SpellingOptions 클래스)에 적용하여 식별합니다.

    ' Visual Basic
     
    ' SpellingOptions 클래스에 적용된 TypeConverter 특성
    <TypeConverter(GetType(SpellingOptionsConverter)), _
    DescriptionAttribute("응용 프로그램에 대한 맞춤법 검사 옵션이 표시되도록 확장합니다.")> _
    Public Class SpellingOptions
       ...
    End Class
     
     
    //C#
     
    // SpellingOptions 클래스에 적용된 TypeConverter 특성. 
     [TypeConverterAttribute(typeof(SpellingOptionsConverter)),
    DescriptionAttribute("응용 프로그램에 대한 맞춤법 검사 옵션이 표시되도록 확장합니다.")]
    public class SpellingOptions{ ... }

옵션 창 응용 프로그램을 다시 컴파일하고 실행합니다. 다음 스크린 샷에서는 옵션 창의 현재 모양을 보여줍니다.

그림 6. PropertyGrid에 표시되는 형식 변환기가 있는 사용자 지정 데이터 형식

그림 6. PropertyGrid에 표시되는 형식 변환기가 있는 사용자 지정 데이터 형식

참고    확장 가능한 개체만 지원하고 사용자 지정 문자열 표현은 지원하지 않으려면TypeConverterAttribute를 클래스에 적용할 수 있습니다. ExpandableObjectConverter를 형식 변환기 형식으로 지정합니다.

도메인 목록 및 간단한 드롭다운 속성 지원 추가

Enum 형식을 기반으로 열거를 반환하는 속성의 경우 PropertyGrid에서 드롭다운 목록에 열거 값을 자동으로 표시합니다. EnumConverter에서도 이 기능을 제공합니다. 사용자 속성의 경우 Enum을 기준으로 하지 않는 형식을 가진 사용자에게 유효한 값 목록을 제공할 수 있습니다. 이 목록을 선택 목록 또는 도메인 목록이라고도 합니다. 도메인 값이 런타임까지도 알려지지 않거나 값이 변경될 수 있는 경우가 이런 경우입니다.

옵션 창을 수정하여 사용자가 선택할 수 있는 기본 파일 이름의 도메인 목록을 제공합니다. DefaultFileName 속성을 AppSettings 클래스에 이미 추가했습니다. 다음 단계에서는 도메인 목록을 제공하기 위해 PropertyGrid에 속성의 드롭다운을 표시합니다.

간단한 드롭다운 속성 지원을 제공하려면
  1. 형식 변환기 클래스에서 상속되는 클래스를 만듭니다. DefaultFileName 속성이 String 형식이기 때문에StringConverter에서 상속할 수 있습니다. 사용자의 속성 형식에 대한 형식 변환기가 없으면 TypeConverter에서 상속할 수 있습니다. 그러나 이 경우에는 필요하지 않습니다.

    ' Visual Basic
     
    Public Class FileNameConverter
        Inherits StringConverter
    End Class
     
     
    //C#
     
    public class FileNameConverter: StringConverter 
    {  } 
  2. GetStandardValuesSupported 메서드를 재정의하고 true를 반환하여 이 개체가 목록에서 선택할 수 있는 표준 값 세트를 지원함을 나타냅니다.

    ' Visual Basic
     
    Public Overloads Overrides Function GetStandardValuesSupported( _
                        ByVal context As ITypeDescriptorContext) As Boolean
        Return True
    End Function
     
     
    //C#
     
    public override bool GetStandardValuesSupported(
                               ITypeDescriptorContext context) 
    {
        return true;
    }
  3. GetStandardValues 메서드를 재정의하고 표준 값으로 채워진 StandardValuesCollection을 반환합니다.StandardValuesCollection을 만드는 한 가지 방법은 생성자에 값 배열을 제공하는 것입니다. 옵션 창 응용 프로그램의 경우 제안된 기본 파일 이름으로 채워진 String 배열을 사용할 수 있습니다.

    ' Visual Basic
     
    Public Overloads Overrides Function GetStandardValues( _
                         ByVal context As ITypeDescriptorContext) _
                      As StandardValuesCollection
     
        Return New StandardValuesCollection(New String() {"새 파일", _
                                                          "파일1", _
                                                          "문서1"})
    End Function 
     
     
    //C#
     
    public override StandardValuesCollection
                         GetStandardValues(ITypeDescriptorContext context) 
    {
        return new StandardValuesCollection(new string[]{"새 파일", 
                                                         "파일1", 
                                                         "문서1"});
    } 
  4. (옵션) 사용자가 드롭다운 목록에 없는 값을 입력할 수 있게 하려면 GetStandardValuesExclusive 메서드를 재정의하고 false를 반환합니다. 그렇게 하면 기본적으로 드롭다운 목록 스타일이 콤보 상자 스타일로 바뀝니다.

    ' Visual Basic
     
    Public Overloads Overrides Function GetStandardValuesExclusive( _
                   ByVal context As ITypeDescriptorContext) As Boolean
        Return False
    End Function
     
     
    //C#
     
    public override bool GetStandardValuesExclusive(
                               ITypeDescriptorContext context) 
    {
        return false;
    }
  5. 이제 드롭다운 목록을 표시하기 위한 사용자 형식 변환기 클래스를 만들었으므로 이 형식 변환기 클래스를 사용할 대상을 식별해야 합니다. 이 경우에는 형식 변환기가 속성에 한정되기 때문에 대상이 DefaultFileName 속성입니다. TypeConverterAttribute를 대상 속성에 적용합니다.

    Visual Basic
     
    ' DefaultFileName 속성에 적용된 TypeConverter 특성
    <TypeConverter(GetType(FileNameConverter)), , _
     CategoryAttribute("문서 설정")> _
    Public Property DefaultFileName() As String
        Get
            Return _defaultFileName
        End Get
        Set(ByVal Value As String)
            _defaultFileName = Value
        End Set
    End Property
     
     
    //C#
     
    // DefaultFileName 속성에 적용된 TypeConverter 특성 
    [TypeConverter(typeof(FileNameConverter)), 
     CategoryAttribute("문서 설정")]
    public string DefaultFileName
    {
        get{ return defaultFileName; }
        set{ defaultFileName = value; }
    }

옵션 창 응용 프로그램을 다시 컴파일하고 실행합니다. 다음 스크린 샷에서는 옵션 창의 현재 모양을 보여줍니다. DefaultFileName 속성이 표시되는 모양에 주의합니다.

그림

그림 7. PropertyGrid    드롭다운   도메인   목록   표시

속성에 대한 사용자 지정 UI 제공

앞에서 설명한 것처럼 .NET Framework 형식은 TypeConverter 및 UITypeEditor 클래스를 다른 클래스와 함께 사용하여 PropertyGrid 편집 지원을 제공합니다. 사용자 지정 형식 지원 절에서는 TypeConverter 사용을 살펴보았습니다.UITypeEditor 클래스를 사용하여 PropertyGrid를 사용자에 맞게 지정할 수도 있습니다.

Image 및 Color 클래스용으로 제공되는 것과 비슷한 작은 그래픽 표현을 PropertyGrid에 속성 값과 함께 제공할 수 있습니다. 사용자에 맞게 설정하기 위해 이렇게 하려면 UITypeEditor에서 상속하고, GetPaintValueSupported를 재정의한 다음 true를 반환합니다. 그런 다음 UITypeEditor.PaintValue 메서드를 재정의하고, 사용자 메서드에서PaintValueEventArgs.Graphics 매개 변수를 사용하여 그래픽을 그립니다. 마지막으로 UITypeEditor 클래스를 사용하는 속성 또는 클래스에 Editor 특성을 적용합니다.

다음 스크린 샷에서는 결과 모양을 보여줍니다.

그림

그림 8. PropertyGrid    속성에   대한   사용자   지정   그래픽   표시

Control.Dock 속성에서 사용자 도킹 선택을 제공할 때 사용하는 것과 비슷한 사용자 드롭다운 목록 컨트롤을 제공할 수도 있습니다. 그렇게 하려면 UITypeEditor에서 상속하고, GetEditStyle을 재정의하고, DropDown과 같은UITypeEditorEditStyle 열거 값을 반환합니다. 사용자 지정 드롭다운 컨트롤은 Control 또는 Control 파생 클래스(예:UserControl)에서 상속해야 합니다. 그런 다음, UITypeEditor.EditValue 메서드를 재정의합니다.IServiceProvider.GetService 메서드를 호출하는 IServiceProvider 매개 변수를 사용하여IWindowsFormsEditorService 인스턴스를 가져옵니다. 마지막으로IWindowsFormsEditorService.DropDownControl 메서드를 호출하여 사용자 지정 드롭다운 목록 컨트롤을 표시합니다. UITypeEditor 클래스를 사용하는 속성 또는 클래스에 Editor 특성을 적용해야 합니다.

다음 스크린 샷에서는 결과 모양을 보여줍니다.

그림

그림 9. PropertyGrid    속성에   대한   사용자   지정   드롭다운   컨트롤   표시

TypeEditor 및 UITypeEditor 클래스를 사용하는 것 외에 PropertyGrid를 사용자에 맞게 설정하여 추가 속성 탭을 표시할 수도 있습니다. 속성 탭은 PropertyTab 클래스에서 상속됩니다. Microsoft Visual C# .NET에서 속성 브라우저를 사용한 경우 사용자 지정 PropertyTab이 표시됩니다. Events 탭(번개 표시가 있는 단추)은 사용자 지정PropertyTab입니다. 다음 스크린 샷에서는 사용자 지정 PropertyTab이 아래에 표시되는 다른 예제를 보여줍니다. 이PropertyTab은 단추의 경계 지점을 편집하여 사용자 지정 단추 모양을 만들 수 있는 기능을 제공합니다.

그림

그림 10. PropertyGrid    사용자   지정      표시

UITypeEditor 클래스를 사용하여 PropertyGrid를 사용자에 맞게 설정하는 방법과 위의 사용자 지정 사용자 인터페이스에 대한 자세한 내용은 Shawn Burke의 기사 Make Your Components Really RAD with Visual Studio .NET Property Browser  tous.gif 를 참조하십시오.

결론

.NET Framework에서 제공하는 ProperyGrid 컨트롤에서는 사용자 인터페이스를 개선하기 위해 사용할 수 있는 풍부한 편집 경험을 제공합니다. PropertyGrid를 사용자에 맞게 설정하는 것이 얼마나 쉬운지 알게되면 응용 프로그램에서PropertyGrid를 사용할 것입니다. 또한, Visual Studio .NET 속성 브라우저는 PropertyGrid를 기반으로 하기 때문에 이 기술을 사용하여 보다 풍부한 디자인 타임 경험을 제공할 수 있습니다.

최종 수정일: 2002년 8월 1일

반응형

'Programming > C#' 카테고리의 다른 글

PropertyGrid Attribute FileSelectorTypeEditor  (0) 2011.10.27
C#을 이용한 PropertyGrid 사용법에 대한 Summary  (0) 2011.10.27
ContextMenuStrip Item 동적 제어  (0) 2011.10.26
Windows Forms FAQ  (0) 2011.10.25
[링크] WinForm Study  (0) 2011.10.25
Posted by blueasa
, |
1) ContextMenuStrip의 Opening 이벤트
private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
{
   
ContextMenuStrip cmnu = (ContextMenuStrip)sender;
    cmnu
.Items[1].Enabled = false;
}


출처 : http://stackoverflow.com/questions/4690229/how-to-disable-toolstripmenuitem-in-context-menu-dynamically


2) Items 루프 돌면서 비교 제어(for)
               for (int i = 0; i < contextMenuStripAction.Items.Count; i++)
                {
                    String text = contextMenuStripAction.Items[i].Text;
                   
                    contextMenuStripAction.Items[i].Enabled = false;
                }


3) Items 루프 돌면서 비교 제어(foreach)
                foreach (ToolStripItem c in contextMenuStripAction.Items)
                {
                    if (c is ToolStripMenuItem)
                    {
                        ToolStripMenuItem t = new ToolStripMenuItem();
                        t = (ToolStripMenuItem)c;
                        t.Enabled = false;
                    }
                }

반응형
Posted by blueasa
, |

Windows Forms FAQ

Programming/C# / 2011. 10. 25. 19:10
반응형

'Programming > C#' 카테고리의 다른 글

PropertyGrid 컨트롤 최대 활용  (0) 2011.10.26
ContextMenuStrip Item 동적 제어  (0) 2011.10.26
[링크] WinForm Study  (0) 2011.10.25
XML 특정 하위노드 및 자식노드를 좀 간단히 읽어보기  (0) 2011.10.25
[C#] xml 파싱  (0) 2011.10.25
Posted by blueasa
, |