C# 索引器属性的 PropertyChanged
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/657675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PropertyChanged for indexer property
提问by Inferis
I have a class with an indexer property, with a string key:
我有一个带有索引器属性的类,带有一个字符串键:
public class IndexerProvider {
public object this[string key] {
get
{
return ...
}
set
{
...
}
}
...
}
I bind to an instance of this class in WPF, using indexer notation:
我使用索引器表示法绑定到 WPF 中此类的一个实例:
<TextBox Text="{Binding [IndexerKeyThingy]}">
That works fine, but I want to raise a PropertyChanged
event when one of the indexer values changes. I tried raising it with a property name of "[keyname]" (i.e. including [] around the name of the key), but that doesn't seem to work. I don't get binding errors in my output window whatsoever.
这工作正常,但我想PropertyChanged
在索引器值之一发生变化时引发一个事件。我尝试使用“[keyname]”的属性名称来提升它(即在密钥名称周围包含 []),但这似乎不起作用。我的输出窗口中没有任何绑定错误。
I can't use CollectionChangedEvent, because the index is not integer based. And technically, the object isn't a collection anyway.
我不能使用 CollectionChangedEvent,因为索引不是基于整数的。从技术上讲,该对象无论如何都不是集合。
Can I do this, and so, how?
我可以这样做吗,所以,怎么做?
采纳答案by Jb Evain
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.
根据此博客条目,您必须使用"Item[]"
. Item 是编译器在使用索引器时生成的属性的名称。
If you want to be explicit, you can decorate the indexer property with an IndexerNameattribute.
如果您想要明确,您可以使用IndexerName属性来修饰 indexer属性。
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.
至少它使意图更加明确。不过,我不建议您更改索引器名称,如果您的好友发现该字符串是"Item[]"
硬编码的,则可能意味着 WPF 将无法处理不同的索引器名称。
回答by dimondwoof
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:
实际上,我认为将 IndexerName 属性设置为“Item”是多余的。IndexerName 属性专门用于重命名索引,如果您想为其集合项指定不同的名称。所以你的代码可能是这样的:
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.
一旦您将索引器名称设置为您想要的任何名称,您就可以在 FirePropertyChanged 事件中使用它。
回答by ghord
Additionaly, you can use
另外,您可以使用
FirePropertyChanged ("Item[IndexerKeyThingy]");
To notify only controls bound to IndexerKeyThingy on your indexer.
仅通知绑定到索引器上的 IndexerKeyThingy 的控件。
回答by Andrew Elford
There are at least a couple of additional caveats when dealing with INotifyPropertyChang(ed/ing) and indexers.
在处理 INotifyPropertyChang(ed/ing) 和索引器时,至少有几个额外的注意事项。
The first is that most of the popular methodsof 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.
首先是大多数避免魔法属性名称字符串的流行方法都是无效的。由[CallerMemberName]
属性创建的字符串在末尾缺少“[]”,并且 lambda 成员表达式根本无法表达该概念。
() => 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 otherpostshave 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.
其他几篇文章曾经Binding.IndexerName
避免使用 string literal "Item[]"
,这是合理的,但引发了第二个潜在问题。对 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[]";
}
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.
"Item[]"
作为常量值的重复使用表明 WPF 期望它是在 PropertyChanged 事件中传递的名称,并且,即使它不关心实际的属性被调用(我没有确定我满意的是方式或其他),避免使用[IndexerName]
将保持一致性。