PropertyChanged for indexer property

后端 未结 4 569
天命终不由人
天命终不由人 2020-12-01 04:11

I have a class with an indexer property, with a string key:

public class IndexerProvider {
    public object this[string key] {
        get
        {
                


        
相关标签:
4条回答
  • 2020-12-01 04:55

    According to this blog entry, you have to use "Item[]". Item being the name of the property generated by the compiler when using an indexer.

    If you want to be explicit, you can decorate the indexer property with an IndexerName attribute.

    That would make the code look like:

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

    At least it makes the intent more clear. I don't suggest you change the indexer name though, if your buddy found the string "Item[]" hard coded, it probably means that WPF would not be able to deal with a different indexer name.

    0 讨论(0)
  • 2020-12-01 04:55

    Additionaly, you can use

    FirePropertyChanged ("Item[IndexerKeyThingy]");
    

    To notify only controls bound to IndexerKeyThingy on your indexer.

    0 讨论(0)
  • 2020-12-01 04:59

    There are at least a couple of additional caveats when dealing with INotifyPropertyChang(ed/ing) and indexers.

    The first is that most of the popular methods of avoiding magic property name strings are ineffective. The string created by the [CallerMemberName] attribute is missing the '[]' at the end, and lambda member expressions have problems expressing the concept at all.

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

    Several other posts have used Binding.IndexerName to avoid the string literal "Item[]", which is reasonable, but raises the second potential issue. An investigation of the dissasembly of related parts of WPF turned up the following segment in 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[]";
      }
    

    The repeated use of "Item[]" as a constant value suggests that WPF is expecting that to be the name passed in the PropertyChanged event, and, even if it doesn't care what the actual property is called (which I didn't determine to my satisfaction one way or the other), avoiding use of [IndexerName] would maintain consistency.

    0 讨论(0)
  • 2020-12-01 05:16

    Actually, I believe setting the IndexerName attribute to "Item" is redundant. The IndexerName attribute is specifically designed to rename an index, if you want to give it's collection item a different name. So your code could look something like this:

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

    Once you set the indexer name to whatever you want, you can then use it in the FirePropertyChanged event.

    0 讨论(0)
提交回复
热议问题