我正在使用这里的代码片段以及我自己在 Ironpython 中的修改,效果非常好:
from System.ComponentModel import INotifyPropertyChanged, PropertyChangedEventArgs
from Library.pyevent import make_event
class Notify_property(property):
''' defines a notifiable property
'''
def __init__(self, getter):
def newgetter(slf):
#return None when the property does not exist yet
try:
return getter(slf)
except AttributeError:
return None
super(Notify_property, self).__init__(newgetter)
def setter(self, setter):
def newsetter(slf, newvalue):
# do not change value if the new value is the same
# trigger PropertyChanged event when value changes
oldvalue = self.fget(slf)
if oldvalue != newvalue:
setter(slf, newvalue)
slf.OnPropertyChanged(setter.__name__)
return property(
fget=self.fget,
fset=newsetter,
fdel=self.fdel,
doc=self.__doc__)
class NotifyPropertyChangedBase(INotifyPropertyChanged):
''' The base of the MVVM view model
Here the bound properties are added in addition with its
handlers.
'''
# handlers which get fired on any change register here
PropertyChanged = None
''' handlers that only get fired on their property change register here
they are organized in a dictionary with the property name as key and
a list of handlers as value
'''
_property_handlers = {}
def __init__(self):
''' we create an event for the property changed event
'''
self.PropertyChanged, self._propertyChangedCaller = make_event()
def add_PropertyChanged(self, value):
''' helper function to wrap the += behaviour
'''
self.PropertyChanged += value
def remove_PropertyChanged(self, value):
''' helper function to wrap the -= behaviour
'''
self.PropertyChanged -= value
def OnPropertyChanged(self, propertyName):
''' gets fired on an property changed event
'''
if self.PropertyChanged is not None:
self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))
try:
for property_handler in self._property_handlers[propertyName]:
property_handler(propertyName,PropertyChangedEventArgs(propertyName))
except KeyError:
pass
def add_notifiable_property(self, notifiable_property):
self.add_handled_property((notifiable_property,None))
def add_notifiable_property_list(self, *symbols):
for symbol in symbols:
self.add_notifiable_property(symbol)
def add_handled_property_list(self, *symbols):
for symbol in symbols:
self.add_handled_property(symbol)
def add_handled_property(self, notifiable_property):
symbol = notifiable_property[0]
if notifiable_property[1] is not None:
self._property_handlers[notifiable_property[0]] = notifiable_property[1]
dnp = """
import sys
sys.path.append(__file__)
@Notify_property
def {0}(self):
return self._{0}
@{0}.setter
def {0}(self, value):
self._{0} = value
""".format(symbol)
d = globals()
exec dnp.strip() in d
setattr(self.__class__, symbol, d[symbol])
现在我必须承认我没有完全理解所有的代码。主要是 Notify_property 类的使用对我来说是个谜。为了更好地理解代码,我尝试删除一个属性。从我的 MainViewModel 调用,它是上述类的子类,我可以通过以下方式定义一个属性:
add_notifiable_property('TestProperty')
或者
add_handled_property((TestProperty,[handler1,handler2])
我也可以删除处理程序(尚未实现)但如何再次删除属性?
del self.TestProperty
除了
undeletable attribute
和
delattr(self,'TestProperty')
除了
delattr takes exactly 2 arguments 2 given
嗯很奇怪。
我还尝试向我的基类添加一个函数:
def remove_notifiable_property(self,propertyname):
''' removes a notifiable property
'''
self._property_handlers.pop(propertyname,None)
exec "del self.{0}".format(propertyname)
但是对于不可删除的属性会出现相同的错误。
如何再次删除设置的属性?
编辑:我发现我缺少删除器功能。将此代码添加到上述 dnp 字符串现在会导致一个新错误:
@{0}.deleter
def {0}(self):
del self._{0}
出现新错误:
Derived calss has no attribute _TestProperty
TestProperty 是我添加的名称。还是卡住了。
EDIT2:我将其追踪到以下内容:
class C(object):
def __init__(self):
pass#self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
c = C()
print dir(c)
c.x = 'A'
print c.x
print dir(c)
del c.x
print dir (c)
显示相同的行为。错误 no _ 来自缺少初始化属性。添加一个:
exec """self._{0} = None""".format(symbol)
到 add_handled_property 的最后一行修复它。
但是属性本身仍然显示为 dir,而且它不再在类中。这是python中的错误吗?