开发者

WPF Databinding with ObservableCollection

开发者 https://www.devze.com 2023-02-07 03:06 出处:网络
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 ListB

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消