【问题标题】:Get INotifyPropertyChanged on multiple inherited objects在多个继承对象上获取 INotifyPropertyChanged
【发布时间】:2011-11-09 00:14:31
【问题描述】:

好吧,我不认为我的标题很有效率,但无论如何。让我更准确地解释一下。

我有一门课,Vehicle。我创建了两个子类,Car 和 Plane。我想监视速度,这是一个车辆属性,并将其绑定到 WPF 中的控件(例如标签或图像)。当我创建一个静态类时,它的唯一目的是观察 Speed 属性,它可以工作,只要 INotifyPropertyChanged 是用 Speed 属性名称声明的。

但问题是,我必须通过查看 XML 文件并反序列化我的对象并创建多个 Car 或 Plane UserControl 来动态创建多个 Cars 和 Plane(请不要讨论这种工作方式)。所以我必须在 Vehicle 类中获取 Speed 属性(这是正常的),并且我必须在每个创建的车辆的每个 Speed 上获取一个 INotifyPropertyChanged。 因此,我的 Cars 和 Planes 已加载,我必须获得所有速度,但我无法通过 Vehicle 创建静态 Speed 属性。顺便说一句,通过在车辆类中创建一个非静态 Speed 属性(例如 int),并在 setter 中引发 INotifyPropertyChanged,它不起作用。似乎引发了该事件,但我的转换器没有被触发,我的控件也没有更新。

在我的车辆类中

Private SpeedValue As Integer
<XmlIgnore()>
Public Property Speed() As Short
    Get
        Return SpeedValue 
    End Get
    Set(ByVal value As Short)
        SpeedValue = value
        NotifyPropertyChanged("Speed")
    End Set
End Property

Public Event PropertyChanged As PropertyChangedEventHandler _
    Implements INotifyPropertyChanged.PropertyChanged

Private Sub NotifyPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))

End Sub

在我的代码隐藏中

Dim b As Binding = New Binding()
    b.Source = theVehicle
    b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    b.Path = New PropertyPath(theVehicle.Speed)
    b.Path = New PropertyPath("Speed")
    b.Converter = New SpeedValueToPicturePathConverter()
    b.ConverterParameter = GetType(Vehicle)
    img_fonctionnement.SetBinding(Image.SourceProperty, b)

我也尝试过使用 lambda 表达式,但我不知道如何让整个事情发挥作用。我也有一个“已经添加了具有相同密钥的项目”错误,但我更改了我的代码,以至于我不记得如何了。 我知道我的解释很糟糕,但很难解释(而且我是法国人;))。拜托,如果你能帮助我,那就太好了,因为我有点卡在这里。

更新

更多代码:

这是在我的 WatchTower 线程中,每 10 秒执行一次。这里的所有代码都有效

' theConfig is a singleton which represent my XML config file deserialized
' Getting all vehicles declared in this file works by doing this
For Each vehic As Vehicle In theConfig.Vehicles
        Dim realTimeSpeed = server.Read("speed") 'reading the speed on some distant server - don't discuss this, it works fine
        If (Not vehic.Speed = realTimeSpeed) Then
            vehic.Speed = realTimeSpeed
        End If

    Next

这是我为 theConfig XML 文件中声明的每个 Vehicle 添加一个 TabItem 的地方

'This actually works, a tab is added for each vehicle
For Each vehic As Vehicle In theConfig.Vehicles
        Dim vehicTabItem As TabItem = New TabItem()
        vehicTabItem.Header = vehic.Description
        If (TypeOf vehic Is Car) Then
        'Adding the CarView UserControl of my own
            vehicTabItem.Content = New CarView(DirectCast(vehic, Car))
            TabControl1.Items.Add(vehicTabItem)
        ElseIf (TypeOf vehic Is Plane) Then
            vehicTabItem.Content = New PlaneView(DirectCast(vehic, Plane))
            TabControl1.Items.Add(vehicTabItem)

        End If

    Next

这是在 CarView 文件中(WPF 用户控件,代码隐藏)

Public Class CarView

Private theCar As Car

Public Sub New(ByVal theCar As Car)

    InitializeComponent()

    Me.theCar = theCar 

    Dim b As Binding = New Binding("Speed")
    b.Source = theCar
    b.Converter = New SpeedValueToPicturePathConverter()
    b.ConverterParameter = GetType(Vehicle)
    'img_fonctionnement is created in the graphic designer in Visual Studio in xaml
    'Remember, this binding works whn I use a static property just for testing
    img_fonctionnement.SetBinding(Image.SourceProperty, b)

End Sub

这部分的 PlaneView 类几乎相同。

我确认转换器只被触发一次,第一次是在创建选项卡时,因为我在 Convert 函数定义上放置了一个断点。之后,转换器将不再被触发。所以图片img_fonctionnement 显示出来了,但是从不更新。但是 Speed 属性已更新,我发誓。据我所知,在调试器的帮助下,INotifyPropertyChanged(在 Speed 的设置器中)被提升了。

并且“已经添加了具有相同键的项目”(出现在消息框中,而不是作为例外)似乎仅在我对调试器很长时间时才会出现。在正常执行模式下,它永远不会显示。

【问题讨论】:

  • 我不明白你为什么要把你的Speed 属性设为static。对我来说这没有意义。
  • 我不想让它静态化,很明显。但是我可以完成这项工作的唯一方法是通过在另一个静态类中创建的车辆创建特定的速度属性,该类由线程更新(速度每 10 秒更新一次)。我只想将速度作为车辆类中的普通属性,由我的线程更新(实际上我可以这样做),并绑定到 WPF 控件;)

标签: .net vb.net inheritance inotifypropertychanged


【解决方案1】:

我不明白您用于创建绑定的代码。

应该就这么简单:

Dim b As Binding = New Binding("Speed")
b.Source = theVehicle
b.Converter = New SpeedValueToPicturePathConverter()
b.ConverterParameter = GetType(Vehicle)
img_fonctionnement.SetBinding(Image.SourceProperty, b)

如果这没有帮助,可能还有其他问题:

  • theVehicle 真的是正确的实例吗?
  • 该实例的速度真的更新了吗?

【讨论】:

  • 我修改了我的代码以匹配你的。现在,我有错误“已添加具有相同密钥的项目”。我不得不说,每次使用 ForEach 创建 Vehicle 时都会执行您给我的绑定代码,我认为这就是为什么存在重复的“键”。顺便说一句,theVehicle 是正确的实例,速度也正确更新,我每次都用调试器检查。
  • @Asmoth:我有点难以理解你在做什么。你能发布更多代码吗?请展示 foreach、img_fonctionnement 是如何创建的以及异常被抛出的位置。
  • 好的,我在第一篇文章中添加了更多代码。 img_fonctionnement 是使用 Visual Studio 的可视化编辑器创建的。 “已经添加了具有相同密钥的项目”仅在我使用调试器时间过长时显示,所以我认为我们不应该照顾它。这可能是由于我的计时器。无论如何。
  • 如果在 XAML 中设置绑定会发生什么?
  • 我正在尝试,但我现在无法弄清楚整个语法,比如将Car 类型传递给转换器,或者访问后面代码中的theCar 变量。我还在努力。
【解决方案2】:

我的错。我正在刷新一个车辆集合,但我正在使用另一个独立的车辆集合(基于相同的 XML 文件)创建我的选项卡。我创建了一个单例,但我并没有在任何地方使用它。

我太坏了。

谢谢,Daniel,你帮助了我,即使你的回答不是我问题的原因;)

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 1970-01-01
    • 2011-07-07
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    相关资源
    最近更新 更多