sdk:wpf:리소스와_데이터바인딩
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판이전 판다음 판 | 이전 판 | ||
sdk:wpf:리소스와_데이터바인딩 [2017/07/03 18:07] – [데이터 바인딩] kieuns | sdk:wpf:리소스와_데이터바인딩 [2024/04/23 22:44] (현재) – 바깥 편집 127.0.0.1 | ||
---|---|---|---|
줄 1: | 줄 1: | ||
+ | ====== 리소스 ====== | ||
+ | |||
+ | 리소스 : 이미지, | ||
+ | |||
+ | 이런 리소스를 패키지화(? | ||
+ | |||
+ | 리소스는 바이너리, | ||
+ | |||
+ | ===== 바이너리 리소스 ===== | ||
+ | |||
+ | 비트맵 같은 일반적인 것부터 컴파일된 xaml도 리소스로 저장 가능. | ||
+ | |||
+ | * 어셈블리 내부에 저장 | ||
+ | * 느슨한 파일 형태(? | ||
+ | |||
+ | 추가 : 프로젝트에 파일을 추가하고 ' | ||
+ | |||
+ | * Resource : 위성어셈블리(? | ||
+ | * Content : 느슨한파일(? | ||
+ | * 그니까.. 위치만 기록하고 파일 리소스는 바깥에 둔다는 이야기(? | ||
+ | |||
+ | 바이너리 리소스에 접근 | ||
+ | |||
+ | * URI를 통해 xaml이나 코드에서 리소스 접근 가능 | ||
+ | * ' | ||
+ | * 해당 리소스가 없어도 일단 동작은 한다. (예: 이미지 같은거) | ||
+ | |||
+ | 다른 어셈블리에 있는 리소스 접근 | ||
+ | |||
+ | 어셈블리참조; | ||
+ | |||
+ | 라는 규칙이 있다. | ||
+ | |||
+ | * 어셈블리명 \\ ( MyDll; | ||
+ | * 어셈블리명; | ||
+ | * 어셈블리명; | ||
+ | * 어셈블리명; | ||
+ | |||
+ | 사이트 원점에서 리소스 접근하기 | ||
+ | |||
+ | * 용어를 왜 이렇게 복잡하게 쓰는가? 설치된 기준 폴더나 url. | ||
+ | * 설치한 폴더를 기준폴더 , 사이트 원점이라고 부른다. | ||
+ | * 웹에서 실행하는 경우 기본 Url | ||
+ | |||
+ | 표시방법 | ||
+ | |||
+ | * siteOfOrigin : 사이트 원점 키워드 | ||
+ | |||
+ | < | ||
+ | pack:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | 코드에서 리소스 접근 | ||
+ | |||
+ | * xaml 방식의 URI 쓸 수 없고 사이트원점을 URL 등의 전체 경로를 명시 | ||
+ | |||
+ | <code csharp> | ||
+ | Image img = new Image(); | ||
+ | img.Source = new BitmapImage(new Uri(" | ||
+ | </ | ||
+ | |||
+ | 지역화 | ||
+ | |||
+ | 지원 언어(컬쳐)만큼 위성 어셈블리로 분리. | ||
+ | |||
+ | LocBaml 을 이용하면 지역화할 문자열 작업을 간편하게 가능. | ||
+ | |||
+ | |||
+ | |||
+ | ===== 로지컬 리소스 ===== | ||
+ | |||
+ | 프로그래밍 코드에서 만들고 사용할 수 있는 리소스. 동적으로 데이터가 추가/ | ||
+ | |||
+ | * Resource 프로퍼티에 닷넷 객체를 저장하고, | ||
+ | * FrameworkElement, | ||
+ | |||
+ | 하드코딩하는 예제 | ||
+ | <code xml> | ||
+ | <!-- 귀찮아서 아직 안적음 --> | ||
+ | </ | ||
+ | |||
+ | Window.Resouce 에 브러쉬 리소스를 세팅해 놓고 사용하는 방식 | ||
+ | <code xml> | ||
+ | <!-- 귀찮아서 아직 안적음 --> | ||
+ | </ | ||
+ | |||
+ | ====리소스로 정의한 것==== | ||
+ | * SolidColorBrush | ||
+ | * LinearGradientBrush | ||
+ | * Image | ||
+ | |||
+ | 잠시, 리소스로 사용할 수 있는 것들의 부모 클래스 | ||
+ | |||
+ | * System.Windows.Freezable : [[https:// | ||
+ | * System.Windows.Media.Animation.Animatable : [[https:// | ||
+ | * System.Windows.Media.Brush : [[https:// | ||
+ | |||
+ | ====리소스 룩업(찾기)==== | ||
+ | |||
+ | StaticResource 마크업 확장식은 리소스 딕셔너리 (위에서는 Window.Resource 부분)에서 아이템을 가리키는 키(x:Key 로 설정한)를 파라미터로 받는다. | ||
+ | |||
+ | 어느 리소스 딕셔너리에든 있기만 하다면 x:Key로 접근 가능하다. 리소스 딕셔너리느는 상위 부모 엘리먼트 또는 애플리케이션 수준의 것도 있을 수 있다. | ||
+ | |||
+ | 검색 단계 | ||
+ | - 현재의 엘리먼트 리소스 딕셔너리 Resources 컬렉션. (없으면 다음 단계) | ||
+ | - 부모의 것에서 찾기, 반복, 루트 엘리먼트까지 검색 (없으면 다음 단계) | ||
+ | - Application 의 Resources 에서 검색 (없으면 다음 단계) | ||
+ | - 시스템에서 검색 (없으면 다음 단계) | ||
+ | - 이래도 없으면 InvalidOperationException 발생 | ||
+ | |||
+ | ====스태틱vs다이나믹 리소스==== | ||
+ | |||
+ | 키워드 | ||
+ | * StaticResource | ||
+ | * DynamicResource | ||
+ | |||
+ | 스태틱 리소스는 선언된 후에 사용할 수 있다. 다이나믹은 그런 제한은 없다. | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | xmlns=" | ||
+ | xmlns: | ||
+ | Title=" | ||
+ | <!-- | ||
+ | DynamicResource 가 위에서 사용 되어도 에러는 없다. | ||
+ | 아래 리소스 정의 하는 부분에 backgroundBrush 를 추가해서 사용하게끔 한다. | ||
+ | --> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | ... | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | === 리소스 분리해서 별개 파일로 나누기 === | ||
+ | |||
+ | ResourceDictionary 클래스의 MergedDictionaries 프로퍼티를 써서 다른 파일의 리소스를 자신의 컬렉션으로 (리소스로) 합칠 수 있다. 코드보면 이해하기 쉬움. | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 개별 파일은 ResourceDictionary를 루트 엘리먼트로 써야 한다. | ||
+ | 예, file1.xaml | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | xmlns=" | ||
+ | xmlns: | ||
+ | <Image x: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | * 머지된 것들 중, 중복되는게 있으면 마지막 것으로 설정 된다. | ||
+ | |||
+ | === 공유 없는 리소스 === | ||
+ | |||
+ | * x:Shared = ' | ||
+ | |||
+ | ' | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | <Image x: | ||
+ | </ | ||
+ | ... | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | === 프로그래밍 코드에서 리소스 정의하고 적용하기 === | ||
+ | |||
+ | 정의는 간단 | ||
+ | |||
+ | <code csharp> | ||
+ | window.Resources.Add(" | ||
+ | </ | ||
+ | |||
+ | 적용(사용) | ||
+ | |||
+ | **Case Static** | ||
+ | |||
+ | <code xml> | ||
+ | <Button | ||
+ | Background=' | ||
+ | BroderBrush=' | ||
+ | </ | ||
+ | |||
+ | 이걸 코드로 쓰려면, | ||
+ | |||
+ | <code csharp> | ||
+ | Button _btn = new Button(); | ||
+ | _btn.Background = (Brush)_btn.FindResource(" | ||
+ | _btn.BorderBrush = (Brush)_btn.FindReosurce(" | ||
+ | </ | ||
+ | |||
+ | * FindResource 는 못찾으면 예외 날림 | ||
+ | * TryFindResource 는 못찾으면 널 반환 | ||
+ | |||
+ | **Case Dynamic** | ||
+ | |||
+ | <code xml> | ||
+ | <Button | ||
+ | Background=' | ||
+ | BroderBrush=' | ||
+ | </ | ||
+ | |||
+ | <code csharp> | ||
+ | Button _btn = new Button(); | ||
+ | _btn.SetResourceReference(Button.BackgroundProperty, | ||
+ | _btn.SetResourceReference(Button.BorderBrushProperty, | ||
+ | </ | ||
+ | |||
+ | ====== 데이터 바인딩 ====== | ||
+ | |||
+ | Data binding, Template, trigger | ||
+ | |||
+ | System.Windows.Data.Binding 클래스가 핵심. 두개의 프로퍼티를 이용해서 둘 사이에 연결된 채널을 유지한다. | ||
+ | |||
+ | ===== 코드로 바인딩 사용 ===== | ||
+ | |||
+ | 한개의 텍스트 블록과 트리뷰가 있는 화면에서, | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | 트리뷰 아이템을 선택할때마다, | ||
+ | |||
+ | <code csharp> | ||
+ | private void DummyTreeView_SelectedItemChanged( | ||
+ | object sender, | ||
+ | RoutedPropertyChangedEventArgs< | ||
+ | { | ||
+ | currentFolder.Text = DummyTreeView.SelectedItem.ToString(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | 바인딩 하기 | ||
+ | |||
+ | <code csharp> | ||
+ | SetBinding() | ||
+ | BindingOperations.SetBinding( _TARGET_, _TARGET_PROP_, | ||
+ | </ | ||
+ | |||
+ | 바인딩 제거 | ||
+ | |||
+ | <code csharp> | ||
+ | BindingOperations.ClearBinding( _TARGET_, _TARGET_PROP_ ); | ||
+ | // 한개 이상 | ||
+ | BindingOperations.ClearAllBindings(..) | ||
+ | </ | ||
+ | | ||
+ | ===== xaml 바인딩 ===== | ||
+ | |||
+ | Binding 선언으로 사용할 수 있는 마크업 확장식이 있다. \\ | ||
+ | 타겟 프로퍼티에 바인딩 인스턴스를 추가하고 프로퍼티처러 사용할 수 있다. | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | | ||
+ | | ||
+ | < | ||
+ | SelectedItem.Header 일지 SelectedItem 일지는 트리뷰 설정 상태에 따라 | ||
+ | --> | ||
+ | </ | ||
+ | |||
+ | Path 프로퍼티는 생략 될 수 있다. | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | 데이터 바인딩은 수동으로 하니씩 처리하는 것보다, 소스와 타겟 프로퍼티의 연결을 프로그래밍 코드를 통해 쉽게(?) 표현할 수 있다. | ||
+ | |||
+ | Source 프로퍼티 대신 ElementName 프로퍼티를 사용하는데, | ||
+ | Source를 쓰려면 대상 객체가 ResourceDictionary 에 리소스로 정의 되어 있어야 한다. ([[sdk: | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== RelativeSource 바인딩 ==== | ||
+ | |||
+ | Path 프로퍼티 이외에, 자신과 타켓 엘리먼트의 관계를 통해서 바인딩하는 방법이 있다. 이때 쓰는 것이 **RelativeSource ** | ||
+ | |||
+ | * 소스 엘리먼트와 타겟 엘리먼트가 같은 경우 | ||
+ | |||
+ | 일단 넘어가고 다시 정리하자. | ||
+ | |||
+ | ==== 단순 프로퍼티와 바인딩 ==== | ||
+ | |||
+ | 데이터가 표시되는 타겟과 소스 프로퍼티를 동기적으로 유지하려면, | ||
+ | |||
+ | * PropertyChanged 이벤트를 정의하고 있는 System.ComponentModel.INotifyPropertyChanged 인터페이스를 구현한다. | ||
+ | * XXX_Changed 이벤트를 구현해야 한다. XXX 는 값이 변하는 프로퍼티의 이름이다. | ||
+ | |||
+ | 첫번째 방법이 권장되는 방법. | ||
+ | |||
+ | 특정 항목(예를 들면 사진을(photo)가리는 photos)의 컬렉션을 가진 컨트롤이 INotifyPropertyChanged 인터페이스를 구현하도록 수정하면 PropertyChanged 이벤트 발생시 | ||
+ | |||
+ | * Add, Remove, Clear, Insert | ||
+ | |||
+ | 같은 동작에 대응해서 처리할 수 있다. | ||
+ | |||
+ | ObservableCollection 클래스 | ||
+ | |||
+ | 이 코드를 작성할때 필요한 콜렉션 클래스. | ||
+ | |||
+ | <code csharp> | ||
+ | // Photo 라는 속성의 아이템 컬렉션의 일반적인 선언 | ||
+ | public class Photos : Collection< | ||
+ | |||
+ | // INotifyPropertyChagned 와 연동 되는 컬렉션 | ||
+ | public class Photos : ObservableCollection< | ||
+ | </ | ||
+ | |||
+ | **주의** | ||
+ | |||
+ | * 소스프로퍼티 : 닷넷 객체라면 모두. 대신 단순 필드가 아니라 실제 프로퍼티여야 한다. 위의 경우, Photo 프로퍼티 형식으로 내부 데이터가 선언되어 있어야 한다. | ||
+ | * 타겟프로퍼티 : 의존형이어야 한다.(?) | ||
+ | |||
+ | ==== 객체 전체와 바인딩 ==== | ||
+ | |||
+ | 객체 전체와 바인딩 하는 것은.. Path를 사용하지 않고 객체를 소스로 사용한다. | ||
+ | |||
+ | <code xml> | ||
+ | <Label x: | ||
+ | </ | ||
+ | |||
+ | * photos 는 Collection 또는 ObservableCollection 컬렉션 개체 | ||
+ | * UIElement 에서 상속된 객체가 아니라서 ToString() 메소드로 반환된 문자열로만 렌더링 된다. | ||
+ | |||
+ | |||
+ | 주의 : UIElement 전체와 바인딩 할때는 | ||
+ | |||
+ | * 뭘까? InvalidOperationException 예외?< | ||
+ | <Label x: | ||
+ | <Label x: | ||
+ | <!-- ' | ||
+ | </ | ||
+ | * 해결하려면, | ||
+ | < | ||
+ | <Label x: | ||
+ | <!-- 예외를 피해간다. --> | ||
+ | </ | ||
+ | * Label.Content 는 Object 타입이라 형변환이 발생되지 않고 | ||
+ | * TextBlock.Text는 ToString() 로 변환이 발생 되며 < | ||
+ | System.Windows.Controls.Label: | ||
+ | </ | ||
+ | * Text를 온전하게 출력하려면 프로퍼티를 Path로 정확하기 가리켜야 한다.< | ||
+ | < | ||
+ | <Label x: | ||
+ | <!-- 예외를 피해간다. --> | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== 컬렉션에 바인딩 ==== | ||
+ | |||
+ | 초기바인딩 | ||
+ | |||
+ | |||
+ | ListBox 사용하는 경우, ListBox.Items 는 의존 프로퍼티가 아니어서 쓸 수 없다. 대신, ItemsSource 를 사용. \\ | ||
+ | 이 프로퍼티는 IEnumerable 타입이라 컬렉션 객체를 소스로 사용할 수 있다. | ||
+ | |||
+ | <code xml> | ||
+ | <ListBox x: | ||
+ | | ||
+ | </ | ||
+ | |||
+ | 소스 컬렉션의 엘리먼트 변화(추가, | ||
+ | |||
+ | * INotifyCollectionChanged 인터페이스 구현이 필요. | ||
+ | * 하지만, **ObservableCollection**에 \\ INotifyCollectionChanged 와 INotifyCollectionChanged 인터페이스 구현 되어 있으니 | ||
+ | * 이걸 쓰면 된다. | ||
+ | |||
+ | 표시 방법의 개선 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====== 데이터 바인딩 : 재정리 ====== | ||
+ | |||
+ | 글만 읽고서는 알기 어렵다. 여러 케이스를 테스트 해보면서 코드 작성 방법을 익혀야 할듯. | ||
+ | |||
+ | ** 다른 엘리먼트의 텍스트(프로퍼티)를 읽어 오기 ** | ||
+ | |||
+ | <code xml> | ||
+ | <TextBox x: | ||
+ | |||
+ | <!-- 엘리먼트 TargetFolderPath 의 Text 프로퍼티 값을 그대로 반영한다 --> | ||
+ | <TextBox x: | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ** Source를 사용해서 소스와 대상의 바인딩 ** | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | * 브러시 같은 리소스는 알겠다. | ||
+ | * 다른 컨트롤 같은 엘리먼트는 어떻게 리소스로 정의하지? | ||
+ | * 하지 못하는 것 같다. [[sdk: | ||
+ | |||
+ | |||
+ | ===== DataContext : 데이터를 전달 하는 방법 ===== | ||
+ | |||
+ | DataContext | ||
+ | |||
+ | 모든 WPF 컨트롤은 FrameWorkElement 로부터 상속된다. 이 클래스에는 **DataContext** 가 포함되어 있다. | ||
+ | DataContext 에 클래스 형식의 데이터를 바인딩 소스로 설정할 수 있다. | ||
+ | |||
+ | 간단한 예로, | ||
+ | |||
+ | 극단적으로 MainWindow 를 통째로 바인딩 소스로 넘겼다. 윈도우에 대한 프로퍼티를 사용할 수 있게 된다. | ||
+ | |||
+ | <code csharp> | ||
+ | public partial class MainWindow : Window | ||
+ | { | ||
+ | // 극단적으로 MainWindow 를 통째로 바인딩 소스로 넘겼다. 윈도우에 대한 프로퍼티를 사용할 수 있게 된다. | ||
+ | public MainWindow() { | ||
+ | InitializeComponent(); | ||
+ | this.DataContext = this; | ||
+ | } | ||
+ | // ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== ValueConverts : 데이터를 전달 하는 방법 ===== | ||
+ | |||
+ | 타입이 다른 두개의 프로퍼티를 바인딩 하는 경우, 값의 컨버팅 할 필요가 있다. ( 에러가 나거나 원하는 값이 안나오거나 ) | ||
+ | |||
+ | 이럴 때 ValueConverter 사용. xaml 키워드 ' | ||
+ | |||
+ | 코드로 작성 해야 하며, **IValueConverter** 인터페이스를 상속 받는 클래스를 만들어야 한다. | ||
+ | |||
+ | 예제로, 불 값을 **Visibility** 프로퍼티로 컨버팅 하는 경우를 본다. bool 값을 **Visible** , **Collapsed** , **Hidden** 으로 변경한다. | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | < | ||
+ | <!-- 클래스 이름이 xaml 키로 사용 되었다. --> | ||
+ | <!-- x:Name이 아닌 것에 유의(확인 필요!) --> | ||
+ | < | ||
+ | </ | ||
+ | | ||
+ | < | ||
+ | < | ||
+ | Visibility=" | ||
+ | Converter={StaticResource boolToVis}}"> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <code csharp> | ||
+ | public class BooleanToVisibilityConverter : IValueConverter | ||
+ | { | ||
+ | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { | ||
+ | if (value is Boolean) { | ||
+ | return ((bool)value) ? Visibility.Visible : Visibility.Collapsed; | ||
+ | } | ||
+ | return value; | ||
+ | } | ||
+ | |||
+ | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { | ||
+ | throw new NotImplementedException(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Binding 다음에 나올 수 있는 키워드 ===== | ||
+ | |||
+ | %%{Binding%% | ||
+ | |||
+ | * ElementName | ||
+ | * Source | ||
+ | * 조건 : 대상 객체가 ResourceDictionary 에 정의 되어 있어야 한다. | ||
+ | * StaticResource or DynamicResource | ||
+ | * 엘리먼트를 어떻게 리소스로 정의하지? | ||
+ | |||
+ | |||
+ | ===== 컨트롤을 리소스로 정의한 다음 사용하는 예제 ===== | ||
+ | |||
+ | <code xml> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | Fill=" | ||
+ | HorizontalAlignment=" | ||
+ | VerticalAlignment=" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ====== DataBinding 디버깅 ====== | ||
+ | |||
+ | * 문서 : [[https:// | ||
+ | |||
+ | 문법 검사로 발견하지 못한 에러의 경우 | ||
+ | |||
+ | * 문법상 오류는 없지만, 없는 오브젝트를 가리키는 등의 오류 발생시 : Trace Output 으로 찾아본다. | ||
+ | * 값이 생각대로 나오지 않았을 경우. : DebugConverter 로 해결 시도. | ||
+ | |||
+ | ===== TRACE 메시지 출력 ===== | ||
+ | |||
+ | <code xml> | ||
+ | <Window x: | ||
+ | xmlns=" | ||
+ | xmlns: | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | * ' | ||
+ | |||
+ | 출력창에 잘못된 프로퍼티라는 에러 메시지가 뜬다. (뜨나? 다른 예제로 해보니 뜬다.) | ||
+ | |||
+ | < | ||
+ | System.Windows.Data Error: 39 : BindingExpression path error: ' | ||
+ | </ | ||
+ | |||
+ | ==== trace level 조정 ==== | ||
+ | |||
+ | xmal에서 하는 것은 잘 안됐고. 코드로 조정하는게 확실하게 되었다. | ||
+ | |||
+ | * 닷넷 3.5 이상 | ||
+ | * None, Low, Medium, High 로 설정 가능. | ||
+ | |||
+ | <code xml> | ||
+ | <Window x: | ||
+ | xmlns=" | ||
+ | xmlns: | ||
+ | xmlns: | ||
+ | |||
+ | < | ||
+ | < | ||
+ | | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 코드로 조정하는 경우 | ||
+ | |||
+ | <code csharp> | ||
+ | PresentationTraceSources.DataBindingSource.Listeners.Add(new ConsoleTraceListener()); | ||
+ | PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.All; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== ValueConverter 를 사용한 브레이크 포인트 설정 ===== | ||
+ | |||
+ | 그닥 쓸모가.. | ||
+ | |||
+ | IValueConverter 에서 상속되는 디버그용 클래스를 작성 < | ||
+ | |||
+ | <code csharp> | ||
+ | /// < | ||
+ | /// This converter does nothing except breaking the | ||
+ | /// debugger into the convert method | ||
+ | /// </ | ||
+ | public class DatabindingDebugConverter : IValueConverter | ||
+ | { | ||
+ | public object Convert(object value, Type targetType, | ||
+ | object parameter, CultureInfo culture) | ||
+ | { | ||
+ | Debugger.Break(); | ||
+ | return value; | ||
+ | } | ||
+ | |||
+ | public object ConvertBack(object value, Type targetType, | ||
+ | object parameter, CultureInfo culture) | ||
+ | { | ||
+ | Debugger.Break(); | ||
+ | return value; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | xaml 코드에서 브레이크 포인트를 설정할 곳에 추가한다. | ||
+ | |||
+ | * DatabindingDebugConverter 가 클래스거나 그 상위 클래스가 %%xmlns: | ||
+ | |||
+ | DatabindingDebugConverter 클래스가 TestAPP 라는 네임스페이스에 포함되어 있는 것으로 가정. | ||
+ | |||
+ | * 사용할 네임스페이스 : %% xmlns: | ||
+ | * 실제 사용하는 클래스 : %% < | ||
+ | |||
+ | <code xml> | ||
+ | <Window x: | ||
+ | xmlns=" | ||
+ | xmlns: | ||
+ | xmlns: | ||
+ | Title=" | ||
+ | |||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | Converter={StaticResource debugConverter}}" | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||