37

文字列キーを持つインデクサー プロパティを持つクラスがあります。

public class IndexerProvider {
    public object this[string key] {
        get
        {
            return ...
        }
        set
        {
            ...
        }
    }

    ...
}

インデクサー表記を使用して、WPF でこのクラスのインスタンスにバインドします。

<TextBox Text="{Binding [IndexerKeyThingy]}">

PropertyChangedこれで問題なく動作しますが、インデクサー値の 1 つが変更されたときにイベントを発生させたいと考えています。「[keyname]」というプロパティ名 (つまり、キーの名前の前後に [] を含む) で上げてみましたが、うまくいかないようです。出力ウィンドウにバインド エラーはまったく表示されません。

インデックスが整数ベースではないため、CollectionChangedEvent を使用できません。技術的には、オブジェクトはコレクションではありません。

私はこれを行うことができますか?

4

4 に答える 4

53

このブログエントリによると、を使用する必要があります"Item[]"。アイテムは、インデクサーを使用するときにコンパイラーによって生成されるプロパティの名前です。

明示的にしたい場合は、IndexerName属性でインデクサープロパティを装飾できます。

これにより、コードは次のようになります。

public class IndexerProvider : INotifyPropertyChanged {

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

少なくとも、それは意図をより明確にします。インデクサー名を変更することはお勧めしませんが、バディが文字列が"Item[]"ハードコードされていることを発見した場合は、おそらくWPFが別のインデクサー名を処理できないことを意味します。

于 2009-03-18T10:27:46.657 に答える
17

さらに、使用できます

FirePropertyChanged ("Item[IndexerKeyThingy]");

インデクサーの IndexerKeyThingy にバインドされたコントロールのみを通知するには。

于 2011-08-11T09:29:04.587 に答える
7

INotifyPropertyChang(ed/ing) とインデクサーを扱う場合、少なくともいくつかの追加の注意事項があります。

1 つ目は、マジック プロパティ名の文字列を回避する一般的な方法のほとんどが効果がないことです。属性によって作成された文字列[CallerMemberName]には末尾の '[]' がなく、ラムダ メンバー式には概念の表現にまったく問題があります。

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

他の いくつかの投稿Binding.IndexerNameでは文字列リテラルを避けるために使用されています"Item[]"が、これは合理的ですが、2 つ目の潜在的な問題が発生します。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 イベントで渡される名前であることを期待していることを示唆しています。の使用を避けることで[IndexerName]一貫性が保たれます。

于 2014-03-27T19:30:46.603 に答える
5

実際、IndexerName 属性を "Item" に設定するのは冗長だと思います。IndexerName 属性は、コレクション項目に別の名前を付けたい場合に、インデックスの名前を変更するように特別に設計されています。したがって、コードは次のようになります。

public class IndexerProvider : INotifyPropertyChanged {

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

インデクサー名を任意の名前に設定したら、それを FirePropertyChanged イベントで使用できます。

于 2010-07-11T17:16:54.477 に答える