On a WPF Window, I have a simple listbox of decimal values which have an ObservableCollection of Amounts bound to it, a label bound to a Total property that shows the sum of the values below the ListBox, and a TextBox out to the right of the ListBox bound to the selectedItem.Amount property.
When I click on an item in the ListBox I want to be able to edit the selectedItem's value in the textbox that gets populated, tab off the TextBox, and have the listBoxItem update its value and I want the sum to be updated in the Label as well.
I understand how element-to-element databinding works (i.e. ListBox to Textbox) What I am having trouble figuring out is element-to-object databinding(i.e. ListBox/ObservableCollection to the Total property)
Thanks so much!
Here are the two simple classes I have so far:
Public Class TransactionModel
Implements INotifyPropertyChanged
'Public Property Amount As Decimal
Private _amount As Decimal
Public Property Amount As Decimal
Get
Return _开发者_运维技巧amount
End Get
Set(ByVal value As Decimal)
_amount = value
OnPropertyChanged(New PropertyChangedEventArgs("Amount"))
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
If Not e Is Nothing Then
RaiseEvent PropertyChanged(Me, e)
End If
End Sub
End Class
Public Class ViewModel Implements INotifyPropertyChanged
Private oc As ObservableCollection(Of TransactionModel)
Sub New()
oc = New ObservableCollection(Of TransactionModel)
oc.Add(New TransactionModel With {.Amount = 10.0})
oc.Add(New TransactionModel With {.Amount = 20.0})
oc.Add(New TransactionModel With {.Amount = 30.0})
oc.Add(New TransactionModel With {.Amount = 40.0})
End Sub
Public Function GetAmounts() As ObservableCollection(Of TransactionModel)
Return oc
End Function
Private _total As Decimal = 0.0
Public Property Total As Decimal
Get
For Each o In oc
_total += o.Amount
Next
Return _total
End Get
Set(ByVal value As Decimal)
_total = value
OnPropertyChanged(New PropertyChangedEventArgs("Total"))
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
If Not e Is Nothing Then
RaiseEvent PropertyChanged(Me, e)
End If
End Sub
End Class
The first part is to add a TextBox, and bind it to the SelectedItem property on the ListBox. This will cause the TextBox to show the amount for the selected item, and allow the user to update it's value:
<TextBox DataContext="{Binding ElementName=lb1, Path=SelectedItem}"
Text="{Binding Path=Amount}" />
You will then need a property on ViewModel named TotalAmount, and a TextBlock bound to it's value. You will also have to handle PropertyChanged for "Value" and re-raise the event for "TotalAmount", which will cause the View to refresh:
<TextBlock Text="{Binding Path=TotalAmount}"></TextBlock>
and the event handler:
Public Class ViewModel Implements INotifyPropertyChanged
...
Public Sub New()
items = New ObservableCollection(Of TransactionModel)()
Dim tm As New TransactionModel()
tm.PropertyChanged += New PropertyChangedEventHandler(TransactionModel_PropertyChanged)
items.Add(tm)
tm = New TransactionModel()
tm.PropertyChanged += New PropertyChangedEventHandler(TransactionModel_PropertyChanged)
items.Add(tm)
tm = New TransactionModel()
tm.PropertyChanged += New PropertyChangedEventHandler(TransactionModel_PropertyChanged)
items.Add(tm)
End Sub
Private Sub TransactionModel_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
If e.PropertyName = "Amount" Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("TotalAmount"))
End If
End Sub
...
End Class
what you probably want to do is to bind your TextBox and your label to the SelectedItem property of the ListBox
here is some XAML to show you what I mean....
<StackPanel>
<TextBlock Width="248" Height="24" Text="Colors:" TextWrapping="Wrap"/>
<ListBox x:Name="lbColor" Width="248" Height="56">
<ListBoxItem Content="Blue"/>
<ListBoxItem Content="Green"/>
<ListBoxItem Content="Yellow"/>
<ListBoxItem Content="Red"/>
<ListBoxItem Content="Purple"/>
<ListBoxItem Content="Orange"/>
</ListBox>
<TextBlock Width="248" Height="24" Text="You selected color:" />
<TextBlock Width="248" Height="24" Text={Binding ElementName="lbColor"}/>
</StackPanel>
to make your label the sum of the values, you could use a converter and bind directly to the collection.
精彩评论