2009-03-18 3 views
32

인덱서 속성하여 PropertyChanged 그건 잘 작동하지만 인덱서 값 중 하나가 변경되면 PropertyChanged 이벤트를 발생시키고 싶습니다. 나는 "[keyname]"이라는 속성 이름 (키의 이름을 중심으로 [] 포함)을 올리려고 시도했지만 작동하지 않는 것 같습니다. 출력 창에서 바인딩 오류가 발생하지 않습니다.키 문자열로, 내가 인덱서 속성을 가진 클래스가

인덱스가 정수 기반이 아니기 때문에 CollectionChangedEvent를 사용할 수 없습니다. 기술적으로 객체는 컬렉션이 아닙니다.

이렇게 할 수 있습니까?

답변

45

this blog entry에 따르면 "Item[]"을 사용해야합니다. 항목은 인덱서를 사용할 때 컴파일러에서 생성 된 속성의 이름입니다.

명시 적으로 나타내려면 IndexerName 특성을 사용하여 인덱서 속성을 꾸밀 수 있습니다. 같은 코드를 살펴 만들 것

:

public class IndexerProvider : INotifyPropertyChanged { 

    [IndexerName ("Item")] 
    public object this [string key] { 
     get { 
      return ...; 
     } 
     set { 
      ... = value; 
      FirePropertyChanged ("Item[]"); 
     } 
    } 
} 

는 적어도 그것은 의도가 더 명확합니다. 인덱서 이름을 변경하라는 제안은하지 않습니다. 귀하의 친구가 문자열 "Item[]"이 하드 코딩 된 것을 발견하면 WPF가 다른 인덱서 이름을 처리 할 수 ​​없다는 것을 의미합니다.

+0

잘 작동합니다. 이상하게도 Google 검색에서 해당 블로그 게시물을 놓쳤습니다. – Inferis

+1

이 솔루션은 훌륭하게 작동하지만 성가신 한계가 있습니다. 하나의 키에 대해서만 값이 변경되도록 지정할 수 없습니다 ... 따라서 많은 키에 바인딩이있는 경우 모두 새로 고칩니다. –

+0

몇 년 후 지금 'nameof'키워드가 있습니다. 나는 모든'FirePropertyChange' 호출에이 값을 사용하지만 어떤 식 으로든 인덱서를'nameof' 할 수 있습니까? – Flynn1179

5

실제로 "Item"에 대한 IndexerName 특성 설정이 중복되는 것 같습니다. IndexerName 특성은 컬렉션 항목에 다른 이름을 지정하려는 경우 인덱스의 이름을 바꾸도록 특별히 설계되었습니다. 당신은 당신이 원하는대로에 인덱서 이름을 설정하면

public class IndexerProvider : INotifyPropertyChanged { 

    [IndexerName("myIndexItem")] 
    public object this [string key] { 
     get { 
      return ...; 
     } 
     set { 
      ... = value; 
      FirePropertyChanged ("myIndexItem[]"); 
     } 
    } 
} 

, 당신은 다음 FirePropertyChanged 이벤트에서 사용할 수 있습니다 : 그래서 당신의 코드는 다음과 같을 수 있습니다.

15

Additionaly, 당신은 당신의 인덱서에 IndexerKeyThingy에 바인딩 만 컨트롤을 알리려면

FirePropertyChanged ("Item[IndexerKeyThingy]"); 

를 사용할 수 있습니다.

+0

+1 당신이 사전 입력 당 그것을 올릴 수 있다는 것을 아는 것이 유용합니다 – abbottdev

+5

누구든지 성공적으로 이것을 얻었습니까? 그것은 나를 위해 일하지 않습니다. "Item []"만 업데이트를 실행하는 것 같습니다. –

+2

Silverlight 4/5에서는 제대로 작동하지만 WPF 4.6.2에서는 전혀 작동하지 않습니다. 항목 []을 사용해야합니다. – AqD

5

INotifyPropertyChang (ed/ing) 및 인덱서를 처리 할 때 몇 가지 추가주의 사항이 있습니다.

첫 번째는 마법 속성 이름 문자열을 피하는 대부분의 popular methods이 효과적이지 않다는 것입니다. [CallerMemberName] 속성에 의해 생성 된 문자열 끝에 '[]'가 없으며 람다 멤버 표현식에 개념을 표현하는 데 문제가 있습니다. postsother 여러

() => this[] //Is invalid 
() => this[i] //Is a method call expression on get_Item(TIndex i) 
() => this //Is a constant expression on the base object 

은 합리적이지만, 두 번째 잠재적 인 문제를 제기 "Item[]" 리터럴 문자열을 피하기 위해 Binding.IndexerName을 사용했다. WPF 관련 부분의 해체에 대한 조사에서 PropertyPath.ResolvePathParts에서 다음 세그먼트가 나타났습니다.

if (this._arySVI[i].type == SourceValueType.Indexer) 
    { 
    IndexerParameterInfo[] array = this.ResolveIndexerParams(this._arySVI[i].paramList, obj, throwOnError); 
    this._earlyBoundPathParts[i] = array; 
    this._arySVI[i].propertyName = "Item[]"; 
    } 

일정한 값으로 "Item[]"의 반복 사용은 WPF 그것은 (실제 속성이라고하든 상관하지 않는 경우에도, 즉하여 PropertyChanged 이벤트에 전달 된 이름이 될 것으로 기대되고 있음을 시사하는 I 한 가지 또는 다른 방식으로 내 만족을 결정하지 못했습니다. [IndexerName]의 사용을 피하면 일관성을 유지할 수 있습니다.