디자인 타임 개발 문제 해결
업데이트: 2007년 11월
Windows Forms 구성 요소 및 컨트롤에 대해 사용자 지정 디자인 타임 경험을 만들 경우 흔히 다음과 같은 문제가 발생할 수 있습니다.
디자인 타임에 디버깅할 수 없음
컴파일러 오류: "'형식 이름' 형식 또는 네임스페이스 이름을 찾을 수 없습니다."
디자인 타임 오류: "'구성 요소 이름' 구성 요소를 만들지 못했습니다."
디버깅 오류: "잘못된 크로스 스레드 작업: '컨트롤 이름' 컨트롤이 자신이 만들어진 스레드가 아닌 다른 스레드에서 액세스되었습니다."
디자인 타임 오류: "시각적으로 디자인할 수 있는 클래스에서 상속되지 않은 클래스가 들어 있으므로 해당 파일을 디자이너에서 열 수 없습니다."
구성 요소가 삭제된 후 문자 모양이 남아 있음
기본 디자이너 동작이 사용자 지정 동작에 의해 가려짐
의도하지 않은 방식으로 디자이너 이벤트 발생
컬렉션에서 Serialize 실패
디자이너가 UndoEngine 참조를 가져오지 못함
디자인 환경이 구성 요소의 속성 변경을 인식하지 않음
구성 요소나 디자이너 변경 후 디자인 환경 새로 고침
새로 생성된 Windows Form에 대한 FxCop 경고: DoNotInitializeUnnecessarily
Partial 클래스 및 Windows Forms 디자이너
레거시 사용자 지정 컨트롤로 인해 디자이너에서 예기치 않은 동작 발생
호스트된 디자이너의 스마트 태그에서 예외 발생
구성 요소 아이콘이 도구 상자에 표시되지 않음
디자인 타임에 디버깅할 수 없음
다음과 같은 두 가지 방법으로 디자인 코드를 디버깅할 수 있습니다.
코드의 전략적 지점에 MessageBox.Show 호출을 배치합니다.
Visual Studio의 다른 인스턴스에 연결하여 첫 번째 인스턴스의 디자인 환경을 디버깅합니다.
자세한 내용은 방법: 디자인 타임 서비스 액세스를 참조하십시오.
컴파일러 오류: "'형식 이름' 형식 또는 네임스페이스 이름을 찾을 수 없습니다."
System.Design 어셈블리를 참조해야 합니다. 디자이너 관련 형식은 System.Design 어셈블리에 있습니다. 여기에는 System.Windows.Forms.Design 및 System.ComponentModel.Design 네임스페이스의 형식이 포함됩니다.
또한 Imports 또는 using 키워드를 사용하여 필요한 네임스페이스를 가져와야 합니다. 자세한 내용은 방법: Windows Forms에서 디자인 타임 지원 액세스를 참조하십시오.
디자인 타임 오류: "'구성 요소 이름' 구성 요소를 만들지 못했습니다."
도구 상자의 디자인 화면에서 구성 요소나 컨트롤을 만들 때 이 오류가 발생할 수 있습니다. 다음 표에서는 이 오류가 발생할 수 있는 원인 두 가지를 보여 줍니다.
원인 |
설명 |
설명 |
---|---|---|
기본 생성자 누락 |
구성 요소나 컨트롤에는 기본 생성자가 있어야 합니다. 기본 생성자는 매개 변수가 없는 생성자입니다. |
디자인 환경에는 기본 생성자가 있어야 해당 형식의 인스턴스를 만들 수 있습니다. |
구성 요소가 제네릭 형식임 |
구성 요소나 컨트롤은 제네릭 형식, 즉 템플릿 형식이나 매개 변수가 있는 형식이 될 수 없습니다. 디자인 환경은 제네릭 형식을 지원하지 않습니다. |
제네릭 형식이 UserControl에서 파생되고 이를 Visual Studio의 UserControl Test Container에서 실행하려고 하면 다음과 같은 오류가 발생합니다. UserControl 'name'을 만들지 못했습니다. 구성 요소 및 컨트롤이 제네릭 형식이 될 수 없지만 제네릭 형식을 사용할 수는 있습니다. |
디자인 타임 오류: "값은 null일 수 없습니다. 매개 변수 이름: '구성 요소 이름'"
도구 상자의 디자인 화면에서 구성 요소나 컨트롤을 만들 때 이 오류가 발생할 수 있습니다. 이러한 오류는 주로 64비트 어셈블리로 빌드된 구성 요소나 컨트롤을 사용하려고 한 경우에 발생합니다. Visual Studio 디자인 환경에서는 64비트 구성 요소를 지원하지 않습니다.
디버깅 오류: "잘못된 크로스 스레드 작업: '컨트롤 이름' 컨트롤이 자신이 만들어진 스레드가 아닌 다른 스레드에서 액세스되었습니다."
Windows Forms 응용 프로그램에서 다중 스레딩을 사용할 경우 스레드로부터 안전하게 보호되는 방식으로 컨트롤을 호출하도록 주의해야 합니다. 이 예외는 디버거에 의해 발생하며 런타임 시에는 나타나지 않지만 이 문제가 발견되면 해결하는 것이 좋습니다. 자세한 내용은 방법: 스레드로부터 안전한 방식으로 Windows Forms 컨트롤 호출을 참조하십시오.
디자인 타임 오류: "시각적으로 디자인할 수 있는 클래스에서 상속되지 않은 클래스가 들어 있으므로 해당 파일을 디자이너에서 열 수 없습니다."
구성 요소나 컨트롤의 파일에 여러 개의 클래스 정의가 포함될 수 있지만 파일에서 첫 번째 클래스는 디자인할 수 있는 클래스여야 합니다. 파일의 첫 번째 클래스는 IComponent 인터페이스를 구현하거나 Component 클래스 또는 Component를 파생하는 클래스에서 파생되어야 합니다.
구성 요소가 삭제된 후 문자 모양이 남아 있음
사용자 지정 디자이너에서 Adorner 개체를 만들 경우 디자이너가 범위를 벗어나면 디자인 화면에서 그 개체를 삭제해야 합니다. 디자이너의 Dispose 메서드에서 BehaviorServiceAdornerCollection.Remove를 호출하여 Glyph 개체와 관련된 Adorner 및 Behavior 개체를 지웁니다. 자세한 내용은 방법: 디자인 모드에서 컨트롤의 모양과 동작 확장을 참조하십시오.
기본 디자이너 동작이 사용자 지정 동작에 의해 가려짐
기본 컨트롤 디자이너에서는 디자인 화면에서 컨트롤 전체를 다루는 문자 모양을 만듭니다. 이를 본문 문자 모양이라고 부릅니다. 사용자 지정 컨트롤 디자이너에서 본문 문자 모양과 동일한 범위의 문자 모양을 만들 경우 본문 문자 모양과 연결된 기본 Behavior 구현을 가리게 됩니다. 이렇게 하면 스마트 태그 및 문자 모양 크기 조정과 같은 기본 기능이 나타나지 않습니다.
Behavior 개체 간에 메시지를 전달할 수 없으므로 마우스 메시지를 처리하여 이를 기본 Behavior 개체로 전달할 수 없습니다. 컨트롤 전체를 다루는 문자 모양을 구현하는 경우 사용자 지정 디자인 경험의 모양 및 동작 전체를 책임져야 합니다.
의도하지 않은 방식으로 디자이너 이벤트 발생
사용자 지정 디자이너가 ComponentRemovedActiveDesignerChanged 및 SelectionChanged와 같은 디자이너 이벤트에 이벤트 처리기를 연결할 경우 디자이너의 Dispose 메서드에서 이벤트 처리기를 분리해야 합니다.
그렇지 않으면 디자인 타임에 의도하지 않은 동작이 일어날 수 있습니다. 다음 목록에서는 발생할 수 있는 몇 가지의 증상을 보여 줍니다.
오류 메시지 상자: "이 명령을 처리하는 동안 오류가 발생했습니다."
오류 메시지 상자: "개체 참조가 개체의 인스턴스로 설정되지 않았습니다."
구성 요소가 삭제되었거나 디자이너가 닫힌 상태에서 이벤트 처리기가 잘못 호출되었습니다.
컬렉션에서 Serialize 실패
사용자 지정 구성 요소나 컨트롤의 컬렉션 속성을 serialize하려면 DesignerSerializationVisibilityAttribute를 적용하고 이를 Content로 설정합니다. 자세한 내용은 방법: DesignerSerializationVisibilityAttribute가 있는 표준 형식 컬렉션 serialize를 참조하십시오.
디자이너가 UndoEngine 참조를 가져오지 못함
폼이 로드되는 동안 UndoEngine 서비스에 대한 참조를 가져오려고 하면 GetService 메서드는 null을 반환합니다.
폼 로드 과정이 완료될 때까지 UndoEngine 서비스는 만들어지지 않으며 사용할 수 없습니다. 폼이 로드된 후 GetService에 대한 이후의 호출에서 UndoEngine 참조를 반환합니다.
일반적으로 UndoEngine에 대한 참조가 직접 필요한 경우는 거의 없습니다. 이러한 경우는 주로 사용자 작업 때문이며 디자이너가 로드된 후에 발생합니다.
디자인 환경이 구성 요소의 속성 변경을 인식하지 않음
속성을 직접 설정하면 디자인 환경은 구성 요소나 컨트롤의 변경 사항을 인식하지 않습니다. ComponentChanged와 같은 이벤트를 발생시키려면 PropertyDescriptor.SetValue 메서드를 사용하여 구성 요소의 속성 값을 설정해야 합니다. 이는 속성 변경을 디자인 환경에 알리며 디자인 화면 및 PropertyGrid 컨트롤을 올바르게 업데이트합니다. 자세한 내용은 방법: 디자인 모드에서 컨트롤의 모양과 동작 확장을 참조하십시오.
DesignerAttribute 구문
사용자 지정 디자이너와 이 디자이너에서 디자인하는 컨트롤을 연결하려면 해당 컨트롤에 DesignerAttribute를 적용합니다.
DesignerAttribute 매개 변수를 정확하게 지정해야 합니다. 그렇지 않으면 디자인 환경은 사용자 지정 디자이너를 로드하지 않습니다.
구성 요소나 디자이너 변경 후 디자인 환경 새로 고침
구성 요소의 디자인 타임 측면을 변경한 경우 구성 요소 프로젝트를 다시 빌드해야 합니다. 또한, 현재 열려 있고 이 구성 요소를 사용하는 다른 Windows Forms 프로젝트가 있는 경우 변경 내용을 보려면 프로젝트에 대한 새로 고침을 수행해야 합니다. 일반적으로 구성 요소가 있는 디자인 창을 닫고 다시 열어야 합니다.
새로 생성된 Windows Form에 대한 FxCop 경고: DoNotInitializeUnnecessarily
Windows Forms 디자이너는 Windows Forms 응용 프로그램 프로젝트를 위해 다음 C# 코드를 생성합니다.
private System.ComponentModel.IContainer components = null;
유효한 FxCop 규칙에 따라 FxCop는 "DoNotInitializeUnnecessarily" 경고를 생성할 수 있습니다. 이는 null이 참조 속성에 대한 CLR(공용 언어 런타임) 기본값이기 때문입니다.
디자이너가 components 필드를 null로 초기화하지 않았으면 C# 컴파일러는 다음 경고를 생성합니다.
"Form1.components에는 할당되지 않으므로 항상 null 기본값을 사용합니다."
SuppressMessageAttribute를 사용하여 FxCop 경고를 표시하지 않을 수 있지만 클래스 이름이 바뀔 경우 유지 관리 문제가 발생할 수 있습니다. 따라서 FxCop 경고를 무시하는 것이 좋습니다.
Partial 클래스 및 Windows Forms 디자이너
기본적으로 Windows Forms 디자이너에서는 구성 요소의 주 파일과는 다른 별개의 전용 파일로 디자이너 serialization 코드를 내보냅니다. 예를 들어, Windows Forms 응용 프로그램 프로젝트에서는 다음 표와 같이 Form1 클래스의 정의가 두 파일로 분할합니다.
파일(C# 파일 이름) |
함수 |
---|---|
Form1.cs |
주 클래스 파일 |
Form1.Designer.cs |
디자이너에서 내보낸 코드 |
파일(VB 파일 이름) |
함수 |
---|---|
Form1.vb |
주 클래스 파일 |
Form1.Designer.vb |
디자이너에서 내보낸 코드 |
일반적으로 Windows Forms 디자이너에서 생성된 코드를 수정할 필요가 없습니다. 대신 주 클래스 파일을 편집합니다.
Windows Forms 디자이너는 partial 키워드를 사용하여 Form1 구현을 서로 다른 두 개의 파일로 분할합니다. 이렇게 하면 디자이너에서 내보낸 코드가 사용자 코드와 섞이지 않습니다. partial 키워드에 대한 자세한 내용은 Partial 클래스 및 메서드(C# 프로그래밍 가이드) 및 Partial(Visual Basic)을 참조하십시오.
Windows Forms 디자이너에서는 디자인할 수 있는 형식의 정의를 세 가지 이상의 partial 구현으로 나눌 수 없습니다. 이 제한에는 해당 형식의 세 번째 partial 정의가 포함된 새 클래스 파일을 생성할 뿐만 아니라 주 파일 또는 디자이너 파일에서 형식의 세 번째 partial 클래스 정의를 추가하는 것도 포함됩니다. 이렇게 정의된 구성원은 Windows Forms 디자이너에 표시되지 않습니다.
레거시 사용자 지정 컨트롤로 인해 디자이너에서 예기치 않은 동작 발생
디자이너에서 형식이 무효화되면 ComponentSerializationService에서는 부분적 다시 로드를 수행하여 업데이트된 형식으로 디자이너를 새로 고칩니다. Visual Studio 2005 이전 버전의 Visual Studio에서는 디자이너가 전체적으로 다시 로드됩니다. Visual Studio 2005의 부분적 다시 로드 동작은 전체를 다시 로드하는 것보다 빠르며 실행 취소 스택도 유지됩니다.
Visual Studio 2005 이전 버전에서 만들어진 구성 요소 및 해당 serializer의 경우 부분적 다시 로드를 수행할 수 없는 경우도 있습니다. 이러한 구성 요소와 컨트롤은 전체를 다시 로드하는 동안에만 deserialize되도록 만들어졌으므로 이로 인해 예기치 않은 동작이 발생할 수 있습니다. 예를 들어, 레거시 컨트롤이 있을 때 Windows Forms 디자이너에서 스택 오버플로, 무응답 또는 빈 영역이 발생할 수 있습니다.
devenv.exe.config 파일에 다음 설정을 추가하여 전체를 다시 로드하는 동작으로 되돌릴 수 있습니다. Visual Studio 2005를 기본 위치에 설치한 경우 이 파일은 C:\Program Files\Microsoft Visual Studio 8\Common7\IDE 폴더에 있습니다.
<appSettings>
<add key="EnableOptimizedDesignerReloading" value="false" />
</appSettings>
호스트된 디자이너의 스마트 태그에서 예외 발생
Visual Studio 외부에서 디자이너를 호스팅할 경우 스마트 태그로 인해 NullReferenceException이 발생할 수 있습니다. 이 문제를 해결하려면 디자이너에서 IUIService 참조를 제공하고 Styles 속성을 구현합니다. 다음 코드 조각에서와 같이 Styles에 의해 노출된 IDictionary에서 "DialogFont" 키로 지정된 요소로 새 Font를 할당합니다.
Styles["DialogFont"] = new Font(...);
구성 요소 아이콘이 도구 상자에 표시되지 않음
Visual Studio에서 ToolboxBitmapAttribute를 사용하여 아이콘을 사용자 지정 구성 요소에 연결할 경우 비트맵은 자동 생성된 구성 요소의 도구 상자에 나타나지 않습니다. 비트맵을 보려면 도구 상자 항목 선택 대화 상자를 사용하여 컨트롤을 다시 로드합니다.