[IronPython] DataBinding from IronPython Object to WPF Property

Steve Apiki sapiki at appropriatesolutions.com
Wed Aug 5 22:50:56 CEST 2009


Hi Dino,

Thanks for your quick answer and for making things clear on INotifyPropertyChanged. 

I'd like to have my own derived classes for this project so I think I'm going to steer clear of ExpandoObject and look into implementing INotifyPropertyChanged.

And I tried out your suggestion for #2, creating a new class:

class Context(object):
    def __init__(self):
        self.person = Person("Alfred")

and then assigning a new Person as the person attribute of the context:

label.DataContext = a_context

def button_click(sender, args):
    a_context.person = Person("Mathilda")

which works (for now) as long as I do the UpdateTarget() and presumably will work as well with implementing INotifyPropertyChanged.

Thanks,

--Steve

----- Original Message -----
From: "Dino Viehland" <dinov at microsoft.com>
To: "Discussion of IronPython" <users at lists.ironpython.com>
Sent: Wednesday, August 5, 2009 4:11:26 PM GMT -05:00 US/Canada Eastern
Subject: Re: [IronPython] DataBinding from IronPython Object to WPF Property

IronPython doesn't actually support INotifyPropertyChanged - it only
supports custom type descriptor so that WPF can get at the values
but it doesn't get the change notifications.

You could make an instance of ExpandoObject which does support it:

import clr
clr.AddReference('Microsoft.Scripting.Core')
from Microsoft.Dynamic import ExpandoObject
a = ExpandoObject()
a.name = 'Foo'

Or you could implement INotifiyPropertyChanged on the Person object
and use a property which fires the event changed notification.

My only thought on #2 would be to add another point of indirection.
So rather than updating the global a_person update a_person.real_value
and have that update fire a bunch of changed events.


> -----Original Message-----
> From: users-bounces at lists.ironpython.com [mailto:users-
> bounces at lists.ironpython.com] On Behalf Of Steve Apiki
> Sent: Wednesday, August 05, 2009 12:58 PM
> To: users at lists.ironpython.com
> Subject: [IronPython] DataBinding from IronPython Object to WPF
> Property
>
> Hello,
>
> I'm working with IronPython 2.6 Beta 1.
>
> I have the following Python class:
>
> class Person(object):
>     def __init__(self, name):
>         self.name = name
>
> I'd like to be able to bind the name property of an instance of this
> class to a WPF textbox control.
>
> I can do this easily enough either in XAML or in code. When the
> application starts, the textbox displays the person's name as expected.
>
> However, if I make changes to the name, say, in response to a button
> click:
>
> def button_click(sender, args):
>     a_person.name += ", jr."
>
> I don't see these changes reflected in the textbox.
>
> I can make this work by calling UpdateTarget on the binding expression
> explicitly:
>
>     exp = BindingOperations.GetBindingExpression(textbox,
> TextBox.TextProperty)
>     exp.UpdateTarget()
>
> but I had thought this would work without the explicit step, since it
> appears that IronPython supports INotifyPropertyChange.
>
> Two questions:
>
> (1) Is it possible to get databinding to work this way without having
> to explicity UpdateTarget?
>
>
> (2) Say instead of the click handler above, we had:
>
> def button_click(sender, args):
>     global a_person
>     a_person = Person("Fred")
>
> In this case, the textbox remains bound to the first Person (which is
> no longer accessible from Python). Is there any way to get the binding
> to re-sync to the new object, short of setting a completely new binding
> to Person("Fred") in code?
>
>
> Full example follows.
>
> Thanks,
>
> --Steve
>
> -----------------------------------------
>
> import clr
> clr.AddReferenceByName("PresentationFramework, Version=3.0.0.0,
> Culture=neutral, PublicKeyToken=31bf3856ad364e35")
> clr.AddReferenceByName("PresentationCore, Version=3.0.0.0,
> Culture=neutral, PublicKeyToken=31bf3856ad364e35")
> clr.AddReferenceByPartialName("IronPython")
> clr.AddReference("IronPython.Modules")
>
> from System.Windows import Application, Window
> from System.Windows.Controls import StackPanel, Button, TextBox
> from System.Windows.Data import Binding, BindingMode, BindingOperations
>
> class Person(object):
>     def __init__(self, name):
>         self.name = name
> a_person = Person("Al")
>
> button = Button()
> button.Content = "Test"
>
> textbox = TextBox()
> textbox.DataContext = a_person
> binding = Binding("name")
> binding.Source = a_person
> binding.Mode = BindingMode.OneWay
> textbox.SetBinding(TextBox.TextProperty, binding)
>
> def button_click(sender, args):
>     """ click handler """
>     a_person.name += ", jr."
>
>     # if you uncomment the following, the textbox is updated
>     # with each button click. If you don't, the text never changes.
>     #exp = BindingOperations.GetBindingExpression(textbox,
> TextBox.TextProperty)
>     #exp.UpdateTarget()
>
> button.Click += button_click
>
>
> window = Window()
> stackpanel = StackPanel()
> stackpanel.Children.Add(button)
> stackpanel.Children.Add(textbox)
> window.Content = stackpanel
>
> Application().Run(window)
>
>
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com

_______________________________________________
Users mailing list
Users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com



More information about the Ironpython-users mailing list