1 Results for '중복된 XAML'

  1. 2007.07.20 [Don't Panic] Value does not fall within the expected range. (3)
오류 리포팅
에러 종류 : System.ArgumentException
예외 메시지 : Value does not fall within the expected range.
스택 덤프(예제) :
at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData)
at System.Windows.DependencyObject.MethodPack(IntPtr objectPtr, String methodName, Object[] rawData)
at System.Windows.DependencyObject.MethodPack(String methodName, Object[] rawData)
at MS.Internal.Collection`1.Add(T value)
at [Namespace].Page.[Method]()

원인
1. 로드한 XAML의 x:Name가 중첩된 경우, 특히 embedded resource로 등록한 XAML을 여러개 로드하여 Canavas에 추가할 때 발생.

샘플 코드
// 동적으로 추가할 xaml 코드 정의
// x:Name이 설정되어 있음에 유의

string xaml = "<Canvas xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' x:Name='testCanvas' />";

// 동적으로 xaml 문자열로부터 엘리먼트를 생성
Canvas cv = XamlReader.Load(xaml) as Canvas;
cv.Width = 50;
cv.Height = 50;
cv.Background = new SolidColorBrush(Color.FromRgb(0xFF, 0x00, 0x00));

// 동적으로 루트 캔버스에 추가
this.Children.Add(cv);

// 똑같은 xaml 문자열로부터 엘리먼트를 생성, 여기까지는 문제 없음
Canvas cv2 = XamlReader.Load(xaml) as Canvas;
cv2.Width = 50;
cv2.Height = 50;
cv2.SetValue<double>(Canvas.LeftProperty, 100);
cv2.Background = new SolidColorBrush(Color.FromRgb(0x00, 0xFF, 0x00));

// 두번째로 생성된 엘리먼트를 추가할 때 x:Name의 중복으로 인한 런타임 예외 발생
this.Children.Add(cv2);

샘플 코드 다운로드 : http://gongdo.tistory.com/attachment/cfile3.uf@211B4A365878F5AD083A41.zip


모든 문제가 대부분 그렇지만, 원인을 찬찬히 생각해보면 당연할거에요. 하지만 이 문제를 처음 접하면 도대체 어디서 잘못해서 이런 예외가 발생했는지 도무지 알 수가 없거든요. 왜냐면 예외에 대한 메시지가 너무 뜬금없어요. '값이 올바른 범위 내에 있지 않습니다.' 이런 메시지만 가지고 x:Name이 중복되었을 거라고 상상할 수 있겠어요? 저도 처음에 이 예외를 만났을 때 정말 오랜 시간 동안 빙빙 돌았던 것 같아요.

샘플 코드를 리뷰하자면, string xaml은 편의상 코드로 바로 적어 넣었지만 아마 외부에 있는 XAML 리소스를 런타임에 읽어온다거나 혹은 DB에 저장되어 있는 XAML 문자열을 읽어 왔다거나 하는 상황일거에요.

여기에서 XamlReader.Load 메서드를 통해 엘리먼트를 생성한 시점에서는 XAML에 문법적인 문제가 없는 한 아무런 예외 없이 잘 만들어 질 거에요. 그런데 이렇게 생성한 엘리먼트를 루트 캔버스에 추가하면 첫 번째는 잘 되다가 두 번째부터 갑자기 안되는 현상으로 나타나겠죠. 이때 착각하기 쉬운게 두 번째 생성도 문제없이 넘어갔기 때문에 XAML 문자열에는 아무런 문제가 없다고 믿어버리게 되는 거에요. 그래서 코드만 죽어라고 뜯어보고 이렇게도 해보고 저렇게도 해보고 삽질을 시작하는 거죠.

즉 디버깅하기 가장 어려운 케이스인 문제의 원인과 에러가 발생하는 위치가 동떨어져 있는데다가 에러 메시지 조차 도무지 무슨 소린지 알 수 없는 경우가 된 거에요.

아직은 이런 케이스를 만나기가 쉽지 않겠지만, 점차 동적으로 XAML을 로드 한다거나 사용자 정의 컨트롤을 작성한다거나 하면서 분명히 이런 문제에 부딪칠 수 있을 거에요.

그럴 때에도 이제는,

DON'T PANIC!

신고
Posted by gongdo


티스토리 툴바