【问题标题】:How to make WPF MVVM Bindings work in python.NET (Cpython)?如何使 WPF MVVM 绑定在 python.NET (Cpython) 中工作?
【发布时间】:2022-10-23 06:40:48
【问题描述】:

我正在尝试使用 python.NET 将this IronPython WPF example 移植到 CPython。

在修复了一些已知问题(adding __namespace__ to the ViewModel class,使用Single Thread Apartment 并将 pyevent.py 的语法更新为 python3)后,我能够让窗口运行,但绑定被忽略:我可以在文本框中写入,但没有事件被触发,并且按钮不会触发 OnClick 方法。

这是完整的代码:

import clr
clr.AddReference(r'wpf\PresentationFramework')
clr.AddReference('PresentationCore')

from System.Windows.Markup import XamlReader
from System.Windows import Application, Window
from System.ComponentModel import INotifyPropertyChanged, PropertyChangedEventArgs
import pyevent
from System.Threading import Thread, ThreadStart, ApartmentState


XAML_str = """<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Sync Paramanager" Height="180" Width="400">
    <StackPanel x:Name="DataPanel" Orientation="Horizontal">
        <Label Content="Size"/>
        <Label Content="{Binding size}"/>
        <TextBox x:Name="tbSize" Text="{Binding size, UpdateSourceTrigger=PropertyChanged}" />
        <Button x:Name="Button" Content="Set Initial Value"></Button>
    </StackPanel>
</Window>"""

class notify_property(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().__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):
    __namespace__ = "NotifyPropertyChangedBase"

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

class ViewModel(NotifyPropertyChangedBase):
    __namespace__ = "WpfViewModel"

    def __init__(self):
        super(ViewModel, self).__init__()
        # must be string to two-way binding work correctly
        self.size = '10'

    @notify_property
    def size(self):
        return self._size

    @size.setter
    def size(self, value):
        self._size = value
        print(f'Size changed to {self.size}')

class TestWPF(object):

    def __init__(self):
        self._vm = ViewModel()
        self.root = XamlReader.Parse(XAML_str)
        self.DataPanel.DataContext = self._vm
        self.Button.Click += self.OnClick

    def OnClick(self, sender, event):
        # must be string to two-way binding work correctly
        self._vm.size = '10'

    def __getattr__(self, name):
        # provides easy access to XAML elements (e.g. self.Button)
        return self.root.FindName(name)


def main():
    tw = TestWPF()
    app = Application()
    app.Run(tw.root)


if __name__ == '__main__':
    thread = Thread(ThreadStart(main))
    thread.SetApartmentState(ApartmentState.STA)
    thread.Start()
    thread.Join()

似乎将 ModelView 分配给 DataPanel 的DataContext 不会触发任何绑定注册,但我不知道如何解决这个问题。

我错过了一些明显的东西吗?

【问题讨论】:

    标签: python wpf python.net


    【解决方案1】:

    不幸的是,pythonnet 不支持在 xaml 文件中定义绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      • 2014-07-12
      • 2011-07-27
      相关资源
      最近更新 更多