Get INotifyPropertyChanged on multiple inherited objects
Well, i don't think my title is quite efficient, but anyway. Let me explain more precisely.
I have a class, Vehicle. I created two child classes, Car and Plane. I want to monitor the speed, which is a Vehicle Property, and bind it to a control (label, or image, for example) in WPF. When i create a static Class which only purpose is watching the Speed Property, it works, as far as the INotifyPropertyChanged is declared with the Speed Property name.
But the problem is, I have to create dynamicly multiple Cars and Planes by looking in an XML file and deserializing my objects, and creating multiple Car or Plane UserControl (Let's not discuss this way of working, please). So I have to get the Speed property inside the Vehicle Class (which is normal), and I have to get a INotifyPropertyChanged on each Speed of each Vehicle Created. So, my Cars and Planes are loaded, and I have to get all speeds, but I can't create a static Speed property by Vehicle. By the way, by creating a non-static Speed property (as int, for example) in Vehicle Class with INotifyPropertyChanged raised in the setter, it does not work. The event seems to be raised, but my converter is not fired, and my controls does not update.
In my Vehicle Class
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
In my codebehind
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.ConverterPa开发者_运维问答rameter = GetType(Vehicle)
img_fonctionnement.SetBinding(Image.SourceProperty, b)
I tried with lambda expressions, also, but i couldn't figure out how to make the whole thing work. I also had an "an item with the same key has already been added" error, but I so changed my code that I cannot remember how. I know my explaination is bad, but it is pretty hard to explain (and I'm French ;)). Please, if you could help me, it would be nice, because I'm a bit stuck here.
UPDATE
More code :
This is in my WatchTower Thread, which execute every 10 secondes. All this code here works
' 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
This is where I add a TabItem for each Vehicle declared in the theConfig XML file
'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
This is inside a CarView file (WPF usercontrol, codebehind)
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
The PlaneView Class is almost the same for this part.
I confirm that the converter is fired just once, the first time, when the tabs are created, because I put a breakpoint on the Convert function definition. After that, the converter is never fired again. So the picture img_fonctionnement
is displayed, but it is never updated. But the Speed property is updated, I swear. And the INotifyPropertyChanged (in Speed's setter) is raised, as far as i know with the help of the debugger.
And the "an item with the same key has already been added" (which appears in a messageBox, and not as an exception) seems to appear only when I am to long with the debugger. In normal execution mode, it never shows.
I don't understand the code you are using to create the binding.
It should be as simple as that:
Dim b As Binding = New Binding("Speed")
b.Source = theVehicle
b.Converter = New SpeedValueToPicturePathConverter()
b.ConverterParameter = GetType(Vehicle)
img_fonctionnement.SetBinding(Image.SourceProperty, b)
If this doesn't help, there might be other problems:
- Is
theVehicle
really the correct instance? - Is the speed of that instance really updated?
My bad. I was refreshing a Vehicle Collection, but I was creating my tabs with another independent Vehicle Collection (base on the same XML File). I created a singleton, but i wasn't using it everywhere.
I am so bad.
Thanks, Daniel, you helped me anyway, even if your answer wasn't the cause of my problem ;)
精彩评论