[Python.NET] How to handle INotifyPropertyChanged interface

Denis Akhiyarov denis.akhiyarov at gmail.com
Sun Apr 3 12:08:50 EDT 2016


is it possible to workaround this non-implemented feature by using
___setattr__() hook? seems like people were able to do this in ironpython:

http://stackoverflow.com/questions/3856905/

On Sun, Apr 3, 2016 at 10:40 AM, Tony Roberts <tony at pyxll.com> wrote:

> Yeah, it looks like the crash is probably because of the missing event
> implementation as suspected. I'm a bit surprised that it didn't fail
> earlier when trying to instantiate the type.
>
> If you do get a chance to take a look at adding that functionality be sure
> to submit a pull request!
>
> Best regards,
> Tony
>
>
> On Sun, Apr 3, 2016 at 4:30 PM Hansong Huang <hhspiny at live.com> wrote:
>
>> Tony,
>>
>> thanks for the hint.
>>
>> the event PropertyChanged was declared in INotifyPropertyChanged
>> interface by pythonnet, but obviously not implemented.
>> [('PropertyChanged', <unbound event 'PropertyChanged'>),
>>
>> anyway, the stackoverflow only happens if both following are present
>> 1. the class is derived from INotifyPropertyChanged interface
>> 2. the class exposes property back to .Net vis @clrproperty
>>
>> which seems to prove that it is the PropertyChanged event that is not
>> implemented in python class resulted in the crash.
>>
>> I was not sure if .Net event can be handled by pythonnet. I found a few
>> examples with IronPython, but there, a python class of "event" seems to be
>> implemented instead.
>>
>> Below is the stack trace
>>
>>
>>   [External Code]
>>   clr.dll!CallDescrWorkerInternal () Unknown
>>   clr.dll!CallDescrWorkerWithHandler(struct CallDescrData *,int) Unknown
>>   clr.dll!CallDescrWorkerReflectionWrapper(struct CallDescrData *,class
>> Frame *) Unknown
>>   clr.dll!RuntimeMethodHandle::InvokeMethod(class Object *,class
>> PtrArray *,class SignatureNative *,bool) Unknown
>>   mscorlib.ni.dll!00007fffb86e1ca4() Unknown
>>   mscorlib.ni.dll!00007fffb8618272() Unknown
>>   mscorlib.ni.dll!00007fffb867fc4a() Unknown
>>   [External Code]
>>   mscorlib.ni.dll!00007fffb86dbaf5() Unknown
>>   mscorlib.ni.dll!00007fffb86d281f() Unknown
>>   System.ni.dll!00007fffb77556d4() Unknown
>>   System.ni.dll!00007fffb7755637() Unknown
>>   System.ni.dll!00007fffb775541d() Unknown
>>   PresentationFramework.ni.dll!00007fff96c1ca70() Unknown
>>   PresentationFramework.ni.dll!00007fff96c23902() Unknown
>>   PresentationFramework.ni.dll!00007fff96c22ea1() Unknown
>>   PresentationFramework.ni.dll!00007fff96c22693() Unknown
>>   PresentationFramework.ni.dll!00007fff96c223c9() Unknown
>>   PresentationFramework.ni.dll!00007fff96c21a03() Unknown
>>   PresentationFramework.ni.dll!00007fff96c0d84c() Unknown
>>   PresentationFramework.ni.dll!00007fff96b97299() Unknown
>>   PresentationFramework.ni.dll!00007fff96b9720e() Unknown
>>   PresentationFramework.ni.dll!00007fff96c852f0() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9bc9() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9ac6() Unknown
>>   WindowsBase.ni.dll!00007fff9f6fca2b() Unknown
>>   mscorlib.ni.dll!00007fffb86ca79e() Unknown
>>   mscorlib.ni.dll!00007fffb86ca637() Unknown
>>   mscorlib.ni.dll!00007fffb86ca5f2() Unknown
>>   WindowsBase.ni.dll!00007fff9f913810() Unknown
>>   WindowsBase.ni.dll!00007fff9f6fc784() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f7c24() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f8061() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9e53() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9d82() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9bc9() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f9ac6() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f7583() Unknown
>>   WindowsBase.ni.dll!00007fff9f6f94ff() Unknown
>>   WindowsBase.ni.dll!00007fff9f8c496a() Unknown
>>   clr.dll!UMThunkStub () Unknown
>>   user32.dll!UserCallWinProcCheckWow() Unknown
>>   user32.dll!DispatchMessageWorker() Unknown
>>   WindowsBase.ni.dll!00007fff9f730ee8() Unknown
>>   WindowsBase.ni.dll!00007fff9f70d8fc() Unknown
>>   PresentationFramework.ni.dll!00007fff96af98b3() Unknown
>>   PresentationFramework.ni.dll!00007fff96af969d() Unknown
>>   clr.dll!CallDescrWorkerInternal () Unknown
>>   clr.dll!CallDescrWorkerWithHandler(struct CallDescrData *,int) Unknown
>>   clr.dll!CallDescrWorkerReflectionWrapper(struct CallDescrData *,class
>> Frame *) Unknown
>>   clr.dll!RuntimeMethodHandle::InvokeMethod(class Object *,class
>> PtrArray *,class SignatureNative *,bool) Unknown
>>   mscorlib.ni.dll!00007fffb86e1c20() Unknown
>>   mscorlib.ni.dll!00007fffb8618272() Unknown
>>   [External Code]
>>   clr.dll!UMThunkStub () Unknown
>>   [External Code]
>> > WPFPy.py!threadStart Line 256 Python
>>   [External Code]
>>
>>
>> ------------------------------
>> From: tony at pyxll.com
>> Date: Sun, 3 Apr 2016 15:20:47 +0000
>> Subject: Re: [Python.NET] How to handle INotifyPropertyChanged interface
>> To: hhspiny at pine.cc; pythondotnet at python.org
>>
>>
>> What's the full stack trace?
>>
>> I suspect it's something to do with the event declared on the interface
>> not being implemented. The managed type constructed doesn't define any
>> events, so that would cause the construction of the type of fail - which is
>> probably the error you're getting (although without the stack trace it's
>> just an educated guess).
>>
>> It shouldn't be too hard to add events to the derived type if someone
>> wanted to have a go at implementing it. The code is in the
>> CreateDerivedType method in src/runtime/classderived.cs. To be consistent
>> with how methods and properties work, it would need a clrevent function
>> adding to the clr module (src/runtime/resource/clr.py) - maybe it could
>> work like this:
>>
>> class MyClass(INotifyPropertyChanged):
>>     OnPropertyChanged = clr.clrevent(event_attributes, event_type)
>>
>> Then in classderived.cs the class any clrevents on the python class could
>> be added to the managed type using TypeBuilder.DefineEvent.
>>
>> So, anyway - short answer is that what you're trying to do won't work
>> without changes to pythonnet; but the changes required shouldn't be too
>> hard if you wanted to have a go.
>>
>> Best regards,
>> Tony
>>
>>
>> On Sun, Apr 3, 2016 at 3:37 PM Hansong Huang <hhspiny at live.com> wrote:
>>
>> It seems inheriting from INotifyPropertyChanged is the cause
>>
>> self.window = System.Windows.Markup.XamlReader.Load(outStream)
>> self.window.DataContext = MyViewModel()
>> class MyViewModel(System.Object):
>>     __namespace__ = "WPFPyDemo"
>>     def __init__(self):
>>         super(MyViewModel,self).__init__()
>>         self._inputText = "Line - in"
>>     @clr.clrproperty(str)
>>     def inputText(self):
>>         return self._inputText
>>     @inputText.setter
>>     def inputText(self,value):
>>         self._inputText = value
>>         self.OnPropertyChanged("inputText")
>>
>> The above code works fine.
>>
>> but if switch inheritance to
>> class MyViewModel(System.ComponentModel.INotifyPropertyChanged):
>> and nothing else changed, python gives
>>
>> "The process terminates due to StackOverflowException"
>>
>> Not sure why.
>>
>>
>> Thanks for the help
>>
>> ------------------------------
>> From: hhspiny at live.com
>> To: pythondotnet at python.org
>> Subject: How to handle INotifyPropertyChanged interface
>> Date: Thu, 31 Mar 2016 20:38:38 -0400
>>
>>
>> I am still trying to figure out how to implement WPF MVVM with Python.Net.
>> Previously, I have successfully used System.Dynamic.ExpandoObject as a
>> ViewModel container
>>
>> self.window = System.Windows.Markup.XamlReader.Load(outStream)
>> self.window.DataContext = DotNetExpandoObject()
>>
>> where DotNetExpandoObject is a wrapper class for
>> System.Dynamic.ExpandoObject
>> class DotNetExpandoObject(System.Dynamic.ExpandoObject):
>> ...  in which I redefined __getattr__ and __setattr__
>>
>> it works flawlessly as System.Dynamic.ExpandoObject implements
>> INotifyPropertyChange interface already
>>
>> Now, I would like to get away from using System.Dynamic.ExpandoObject but
>> to implement my own
>>
>> I first tried to expose a python class back to .Net
>> class MyViewModel(System.Object):
>>     __namespace__ = "WPFPyDemo"
>>     def __init__(self):
>>         super(MyViewModel,self).__init__()
>>         self._inputText = "Line - in"
>>     @clr.clrproperty(str)
>>     def inputText(self):
>>         return self._inputText
>>     @inputText.setter
>>     def inputText(self,value):
>>         self._inputText = value
>>         self.OnPropertyChanged("inputText")
>>
>> self.window.DataContext = MyViewModel()
>>
>> The one direction data binding works fine, and the "Line - in" text
>> correctly shows up in the textblock control.
>> obviously this is not sufficient as there is no INotifyPropertyChange
>> interface.
>>
>> So, I inherit the interface , and tries to implement the typical C# code
>> " public event PropertyChangedEventHandler PropertyChanged"
>>
>> -- not sure how to handle event in Python.Net, the follow code probably
>> is completely wrong
>>
>> class ViewModel(System.ComponentModel.INotifyPropertyChanged):
>>     __namespace__ = "WPFPy"
>>     def __init__(self):
>>         super(ViewModel, self).__init__()
>>         self.PropertyChanged =
>> System.ComponentModel.PropertyChangedEventHandler
>>     def OnPropertyChanged(self, propertyName):
>>         if self.PropertyChanged != None:
>>             PropertyChanged(self,
>> System.ComponentModel.PropertyChangedEventArgs(propertyName))
>>
>> class MyViewModel(ViewModel):
>>     __namespace__ = "WPFPyDemo"
>>     def __init__(self):
>>         super(MyViewModel,self).__init__()
>>         self._inputText = "Line - in"
>>
>>     @clr.clrproperty(str)
>>     def inputText(self):
>>         return self._inputText
>>     @inputText.setter
>>     def inputText(self,value):
>>         self._inputText = value
>>         self.OnPropertyChanged("inputText")
>>
>>
>> The process terminates due to StackOverflowException.
>> Looks like the error happens when WFP recoganized INotifyPropertyChange
>> interface and tries to access MyViewModel class via it.
>> _________________________________________________
>> Python.NET mailing list - PythonDotNet at python.org
>> https://mail.python.org/mailman/listinfo/pythondotnet
>>
>>
> _________________________________________________
> Python.NET mailing list - PythonDotNet at python.org
> https://mail.python.org/mailman/listinfo/pythondotnet
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/pythondotnet/attachments/20160403/e88f5e54/attachment-0001.html>


More information about the PythonDotNet mailing list