如何绑定到IronPython中的ListBox?

时间:2011-06-04 03:16:48

标签: wpf binding listbox ironpython

我刚刚开始使用带有WPF的IronPython,我并不清楚如何进行绑定。

通常在WPF中我会做这样的事情:

<ListBox Name="MyListBox">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <DockPanel>
                            <TextBlock Text="{Binding Path=From}" />
                            <TextBlock Text="{Binding Path=Subject}" />
                        </DockPanel>
                     </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.Resources>
</ListBox>

然后在我的代码背后:

MyListBox.ItemsSource = new ObservableCollection<Email>()

但在IronPython中,我们不能有ObservableCollection对象,只能有类型。这不起作用:

MyListBox.ItemsSource = new ObservableCollection[email]()

因为它抛出异常:“期望的数组[类型],得到了classobj”

我该怎么办?求救!

3 个答案:

答案 0 :(得分:4)

我自己解决了这个问题,我有些不对劲,也错过了一些关键点。我希望这个答案可以帮助别人。

首先,您需要来自IronPython目录中tutorial /目录的pyevent.py。

其次我们需要一个助手类:

class NotifyPropertyChangedBase(INotifyPropertyChanged):
    """INotifyProperty Helper"""
    PropertyChanged = None
    def __init__(self):
        (self.PropertyChanged, self._propertyChangedCaller) = make_event()

    def add_PropertyChanged(self, value):
        self.PropertyChanged += value

    def remove_PropertyChanged(self, value):
        self.PropertyChanged -= value

    def OnPropertyChanged(self, propertyName):
        self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))

然后你需要像这样声明你的数据类:

class Email(NotifyPropertyChangedBase):
    """
        use setter getter.
        IronPython 2.6 or later.
    """
    @property
    def From(self):
        return self._From

    @From.setter
    def From(self, value):
        self._From = value
        self.OnPropertyChanged("From")

    @property
    def Subject(self):
        return self._Subject

    @Subject.setter
    def Subject(self, value):
        self._Subject = value
        self.OnPropertyChanged("Subject")

最后设置ListBox的ItemSource:

self.data = ObservableCollection[Email]()
self.MyListBox.ItemsSource = self.data

相信此链接可获得帮助:http://palepoli.skr.jp/wp/2009/06/28/wpf-listview-databinding-for-ironpython/

答案 1 :(得分:3)

扩展boden的答案,您可能想稍微增强NotifyPropertyChangedBase:

class NotifyPropertyChangedBase(INotifyPropertyChanged):
    PropertyChanged = None
    def __init__(self):
        self.PropertyChanged, self._propertyChangedCaller = pyevent.make_event()

    def add_PropertyChanged(self, value):
        self.PropertyChanged += value

    def remove_PropertyChanged(self, value):
        self.PropertyChanged -= value

    def OnPropertyChanged(self, propertyName):
        if self.PropertyChanged is not None:
            self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))

    def init_view(self, view):
        xaml = view
        self.view = XamlLoader(xaml).Root
        self.view.DataContext = self

    def declareNotifiable(self, *symbols):
        for symbol in symbols:
            self.defineNotifiableProperty(symbol)

    def defineNotifiableProperty(self, symbol):
        dnp = """
import sys
sys.path.append(__file__)
from NotifyProperty import *
@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])
        exec("self.{0} = ''".format(symbol))

有了这个设置,你可以做一些像:

class Email(NotifyPropertyChangedBase):
    def __init__(self):
        self.defineNotifiableProperty("From", "Subject")

有了这个,你将获得为defineNotifiableProperty调用中的所有内容设置的@notify_property和@ property.setter项。

答案 2 :(得分:2)

IronPython区分大小写,不使用new关键字。尝试:

MyListBox.ItemsSource = ObservableCollection[Email]()