Как мне выполнить привязку к ListBox в IronPython?

#wpf #binding #listbox #ironpython

#wpf #привязка #listbox #ironpython

Вопрос:

Я только начинаю использовать IronPython с WPF и я не совсем понимаю, как предполагается выполнять привязку.

Обычно в 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 у нас не может быть наблюдаемой коллекции объектов, только типов. Это не работает:

 MyListBox.ItemsSource = new ObservableCollection[email]()
  

Поскольку он выдает исключение: «ожидаемый массив [тип], получен classobj»

Что я должен делать? Помогите, пожалуйста!

Комментарии:

1. Что значит, что это не работает? Он не компилируется? Это вызывает исключение? В чем ваше сообщение об ошибке?

Ответ №1:

Я разобрался с этим сам, у меня было несколько ошибок, а также не хватало нескольких ключевых моментов. Я надеюсь, что этот ответ может помочь кому-то еще.

Сначала было то, что вам нужно pyevent.py из каталога tutorial / в вашем каталоге IronPython.

Во-вторых, нам нужен вспомогательный класс:

 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")
  

Наконец, установите ItemSource для ListBox:

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

Спасибо за помощь по этой ссылке:http://palepoli.skr.jp/wp/2009/06/28/wpf-listview-databinding-for-ironpython /

Комментарии:

1. Кажется, что слишком много шаблонов. Интересно, разработал ли кто-нибудь библиотеку, которая делает это менее болезненным за последние 8 лет.

Ответ №2:

Расширяя ответ Бодена, вы можете захотеть немного улучшить 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")
  

Установив это, вы получите элементы @notify_property и @property.setter, установленные для всего в вызове defineNotifiableProperty.

Ответ №3:

IronPython чувствителен к регистру и не использует new ключевое слово. Попробуйте:

 MyListBox.ItemsSource = ObservableCollection[Email]()