성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] How can I tell whether two programs...
[정성태] The case of the fail-fast crashes c...
[정성태] Creating Docker multi-arch images f...
[정성태] BinaryFormatter removed from .NET 9...
[정성태] Extending the Windows Shell Progres...
[우광현] 와..... 범위를 잡았으니 클라이언트가 해당 범위를 확인해본다...
[정성태] 딱히, 그것 이상으로 더 설명할 내용이 없습니다. 동적 포...
[정성태] If Windows 3.11 required a 32-bit p...
[정성태] What is a hard error, and what make...
[괴물신인] 질문작성자인데 이 글을 이제봤네요 ㄷㄷ 이 글처럼 타입별로 인...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Windows Forms - 속성 창의 디자인 설정 지원: 문자열 목록 내에서 항목을 선택하는 TypeConverter 제작</h1> <p> 아래와 같은 질문이 있군요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > User Control에 string array 속성 추가하는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/3/0/5511'>https://www.sysnet.pe.kr/3/0/5511</a> </pre> <br /> Windows Forms 응용 프로그램은 Visual Studio의 Properties 창과 연동할 수 있는 다양한 디자인-타임 설정들이 존재합니다. 가령, 다음과 같이 컨트롤에 공용 속성을 정의하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.ComponentModel; using System.Windows.Forms; namespace WindowsFormsControlLibrary1 { public partial class UserControl1: UserControl { public UserControl1() { InitializeComponent(); } <span style='color: blue; font-weight: bold'>AccountType _userType; [Category("MyUserControlType")] public AccountType UserType { get { return _userType; } set { _userType = value; } }</span> } public enum AccountType { A, B, C } } </pre> <br /> 다음과 같은 식으로 디자인 창에서 해당 컨트롤의 속성을 Properties 창으로 편집하는 것이 가능합니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='winform_design_time_attr_1.png' src='/SysWebRes/bbs/winform_design_time_attr_1.png' /><br /> <br /> (참고로, Category를 빼면 "Misc" 범주로 포함이 됩니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 질문자는, enum 대신 일련의 문자열 배열을 선택 사항으로 주고 그중에 하나를 취할 수 있는 것을 원하는 듯한데요. 바로 이럴 때 사용할 수 있는 방법이 TypeConverter입니다.<br /> <br /> 우선 기본 구현을 바탕으로,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Building Windows Forms Controls and Components with Rich Design-Time Features, Part 2 ; <a target='tab' href='https://docs.microsoft.com/en-us/archive/msdn-magazine/2003/may/design-time-features-for-windows-forms-controls-and-components'>https://docs.microsoft.com/en-us/archive/msdn-magazine/2003/may/design-time-features-for-windows-forms-controls-and-components</a> User Control Property that shows a list of all Forms at design time ; <a target='tab' href='https://stackoverflow.com/questions/58514948/user-control-property-that-shows-a-list-of-all-forms-at-design-time'>https://stackoverflow.com/questions/58514948/user-control-property-that-shows-a-list-of-all-forms-at-design-time</a> </pre> <br /> 특정 문자열을 반환하는 TypeConverter를 다음과 같이 작성할 수 있고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>public class UserTypeConverter : TypeConverter</span> { public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } public override bool CanConvertTo(ITypeDescriptorContext pContext, Type pDestinationType) { return base.CanConvertTo(pContext, pDestinationType); } public override object ConvertTo(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue, Type pDestinationType) { return base.ConvertTo(pContext, pCulture, pValue, pDestinationType); } public override bool CanConvertFrom(ITypeDescriptorContext pContext, Type pSourceType) { if (pSourceType == typeof(string)) { return true; } return base.CanConvertFrom(pContext, pSourceType); } public override object ConvertFrom(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue) { if (pValue is string) { return pValue.ToString(); } return base.ConvertFrom(pContext, pCulture, pValue); } public override bool GetStandardValuesSupported(ITypeDescriptorContext pContext) { return true; } <span style='color: blue; font-weight: bold'>public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext pContext) { List<string> values = new List<string>(); values.AddRange(new string[] { "UserA", "UserB", "UserC" }); return new StandardValuesCollection(values); }</span> } </pre> <br /> 이것을 UserControl의 속성 하나에 지정하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } AccountType _userType; [Category("MyUserControlType")] public AccountType UserType { get { return _userType; } set { _userType = value; } } string _guestType; [Category("MyUserControlType")] <span style='color: blue; font-weight: bold'>[TypeConverter(typeof(UserTypeConverter))] public string GuestType { get { return _guestType; } set { _guestType = value; } }</span> } </pre> <br /> 다음과 같이 디자인 타임에 문자열을 선택할 수 있습니다.<br /> <br /> <img alt='winform_design_time_attr_2.png' src='/SysWebRes/bbs/winform_design_time_attr_2.png' /><br /> <br /> <hr style='width: 50%' /><br /> <br /> 그런데, 채워줄 문자열 목록을 TypeConverter에 전달해 줄 방법이 없습니다. "[TypeConverter(typeof(UserTypeConverter))]" 특성은 오직 Type 정보만을 인자로 받기 때문인데요, 채워줄 문자열들의 종류 별로 TypeConverter를 만드는 것이 영 못마땅합니다.<br /> <br /> 이에 대한 우회 방법을 찾아 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > How to pass parameter to TypeConverter derived class ; <a target='tab' href='https://stackoverflow.com/questions/14929681/how-to-pass-parameter-to-typeconverter-derived-class'>https://stackoverflow.com/questions/14929681/how-to-pass-parameter-to-typeconverter-derived-class</a> </pre> <br /> 그나마 현실성 있는 방법으로 별도의 특성(Attribute)을 지정해 해결하는 것입니다. 예를 들어, TypeConverter가 선택 목록으로 보여줄 항목을 다음과 같이 StringListAttribute 특성 타입으로 전달하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > string _guestType; [Category("MyUserControlType")] [TypeConverter(typeof(UserTypeConverter))] <span style='color: blue; font-weight: bold'>[StringList(new string[] { "UserA", "UserB", "UserC" })]</span> public string GuestType { get { return _guestType; } set { _guestType = value; } } <span style='color: blue; font-weight: bold'>public class StringListAttribute : Attribute { string[] _list; public string [] List { get { return _list; } } public StringListAttribute(string [] list) { _list = list; } }</span> </pre> <br /> TypeConverter의 GetStandardValues 메서드에서 다음과 같이 해당 속성에 지정된 특성을 열거해 StringList를 찾아 그것에 설정된 목록을 반환하는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext pContext) { List<string> values = new List<string>(); <span style='color: blue; font-weight: bold'>AttributeCollection ua = pContext.PropertyDescriptor.Attributes; foreach (Attribute attr in ua) { if (attr is StringListAttribute listAttr) { values.AddRange(listAttr.List); } }</span> return new StandardValuesCollection(values); } </pre> <br /> 그런대로 이 정도면 해결된 것 같군요. ^^<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1791&boardid=331301885'>첨부 파일은 이 글의 소스 코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1185
(왼쪽의 숫자를 입력해야 합니다.)