question

RogerSchlueter-7899 avatar image
0 Votes"
RogerSchlueter-7899 asked HuiLiu-MSFT commented

How to Respond to a Collection Changed Event

I have two ObservableCollections, ocOrganization and ocVendoers. The Organization object has a ReadOnly property to signal whether an Organization is also a Vendor:

 Public ReadOnly Property IsVendor As Boolean
     Get
         Dim vdr As Vendor = ocVendors.FirstOrDefault(Function(v) v.OrganizationID = clsOrganizationID)
         Return vdr IsNot Nothing
     End Get
 End Property

There is a button on the wpf window that displays each organization that allows the user to make an organization also a vendor. When clicked, I want that ReadOnly property to be reevaluated. To do that I have created this event handler:

   Public Sub VendorsCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
         ????????
     End Sub

So I've got all the pieces in place but I don't know what to replace the "????????" with in the above Sub in order to wire them together. Or is there a different approach altogether that I should be using?



windows-wpfdotnet-visual-basic
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,@ RogerSchlueter-7899. How are your Organization class and Vendoers class defined? Could you show me the code of your collections?

0 Votes 0 ·

My reply got posted as an answer. It is just my reply to your question.

0 Votes 0 ·

Hi,@RogerSchlueter-7899 . Has your problem been solved? I have updated my answer, you can check it.

0 Votes 0 ·
RogerSchlueter-7899 avatar image
0 Votes"
RogerSchlueter-7899 answered
 Public Class Organization
     Implements INotifyPropertyChanged
    
     Public Property OrganizationID As Integer
     <Many more....>
        
     Public ReadOnly Property IsVendor As Boolean
         Get
            Dim vdr As Vendor = ocVendors.FirstOrDefault(Function(v) v.OrganizationID = clsOrganizationID)
            Return vdr IsNot Nothing
         End Get
     End Property
        
     <Other methods>
        
 End Class
    
    
 Public Class Vendor
     Implements INotifyPropertyChanged
    
     Public Property VendorID() As Integer
     Public Property OrganizationID As Integer
     <Many more....>
     <Other methods>
        
 End Class

ocOrganzatiions and ocVendors are the ObservableCollections of those classes.

On my wpf Window there is a button to make an existing organization a vendor:

 Private Sub AddVendor(sender As Object, e As RoutedEventArgs) Handles btnVendor.Click
     cv = New Vendor With
         {
         .IsActive = True,
         .OrganizationID = co.OrganizationID
         }
     ocVendors.Add(cv)
     pnlVendor.DataContext = cv
 End Sub


cv stands for CurrentVendor. pnlVendor is a stackpanel on the window that contains all the controls for the Vendor properties.

After AddVendor is invoked, since ocVendors has changed, I expected the ReadOnly Propety IsVendor to be re-evaluated automatically but apparently I have to do it in code and I don't know how to do that.

I should add that I know I could reove the ":ReadOnly" part and just set IsVendor = True but that seems quite inelegant and unnecessary. I will go that route if there is no other way.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

HuiLiu-MSFT avatar image
0 Votes"
HuiLiu-MSFT answered HuiLiu-MSFT edited

Maybe I didn't ask clearly at the beginning, I want to confirm whether the change of your isVender property is caused by clsOrganizationID? Do you want to set isVender to true when OrganizationID and clsOrganizationID are equal? If so, you could add RaisePropertyChanged("IsVendor") to the get method of clsOrganizationID property to trigger isVender property change. Like the demo below:
The code of xaml:

 <StackPanel>
         <DataGrid Width="400" Height="100" ItemsSource="{Binding OcOrganization, Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged  }" AutoGenerateColumns="False">
             <DataGrid.Columns>
                 <DataGridTextColumn Width="Auto" Header="OrganizationID" Binding="{Binding  OrganizationID}"/>
                 <DataGridTextColumn Width="*" Header="clsOrganizationID" Binding="{Binding clsOrganizationID}"/>
                 <DataGridTextColumn Width="*" Header="is render" Binding="{Binding IsVendor}"/>
             </DataGrid.Columns>
         </DataGrid>
         <DataGrid ItemsSource="{Binding Orders, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="400" AutoGenerateColumns="False" >
             <DataGrid.Columns>
                 <DataGridTextColumn Width="Auto" Header="Name" Binding="{Binding  Name}"/>
                <DataGridTextColumn Width="Auto" Header="Price" Binding="{Binding Price}"/>
                 <DataGridTextColumn Width="Auto" Header="Quantity" Binding="{Binding Quantity}"/>
                 <DataGridTextColumn Width="Auto" Header="TotalPrice" Binding="{Binding TotalPrice}"/>
             </DataGrid.Columns>
         </DataGrid>
     </StackPanel>

The code of xaml.vb:

 Imports System.Collections.ObjectModel
 Imports System.ComponentModel
 Imports Microsoft.VisualBasic.CompilerServices
    
 Partial Public Class MainWindow
     Inherits Window
    
     Public Sub New()
         InitializeComponent()
         Me.DataContext = New ViewModel()
     End Sub
     Friend Class ViewModel
         Implements INotifyPropertyChanged
    
         Private ocVendorsField As ObservableCollection(Of Vendor)
    
         Public Property OCVendors As ObservableCollection(Of Vendor)
             Get
                 Return ocVendorsField
    
             End Get
             Set(ByVal value As ObservableCollection(Of Vendor))
                 ocVendorsField = value
                 RaisePropertyChanged("OCVendors")
             End Set
         End Property
    
         Private ocOrganizationField As ObservableCollection(Of Organization)
    
         Public Property OcOrganization As ObservableCollection(Of Organization)
             Get
                 Return ocOrganizationField
             End Get
             Set(ByVal value As ObservableCollection(Of Organization))
                 ocOrganizationField = value
                 RaisePropertyChanged("OcOrganization")
             End Set
         End Property
    
         Private ordersField As ObservableCollection(Of Order)
    
         Public Property Orders As ObservableCollection(Of Order)
             Get
                 Return ordersField
             End Get
             Set(ByVal value As ObservableCollection(Of Order))
                 ordersField = value
                 RaisePropertyChanged("OCVendors")
             End Set
         End Property
    
         Public Sub New()
             ocVendorsField = New ObservableCollection(Of Vendor) From {
             New Vendor With {
                 .OrganizationID = 0,
                 .clsOrganizationID = 1
             },
             New Vendor With {
                 .OrganizationID = 1,
                 .clsOrganizationID = 1
             }
         }
             ocOrganizationField = New ObservableCollection(Of Organization) From {
             New Organization With {
                 .OrganizationID = 1,
                 .clsOrganizationID = 5,
                 .OCVendors = ocVendorsField
             }
         }
             ordersField = New ObservableCollection(Of Order) From {
             New Order() With {
                 .Name = "apple",
                 .Price = 1.3,
                 .Quantity = 4
             },
             New Order() With {
                 .Name = "orange",
                 .Price = 3.5,
                 .Quantity = 4
             }
         }
         End Sub
    
         Public Event PropertyChanged As PropertyChangedEventHandler _
         Implements INotifyPropertyChanged.PropertyChanged
    
         Public Sub RaisePropertyChanged(ByVal propertyName As String)
             Dim handler As PropertyChangedEventHandler = PropertyChangedEvent
    
             If handler IsNot Nothing Then
                 handler(Me, New PropertyChangedEventArgs(propertyName))
             End If
         End Sub
     End Class
    
     Public Class Vendor
         Implements INotifyPropertyChanged
    
         Private organizationIDField As Integer
    
         Public Property OrganizationID As Integer
             Get
                 Return organizationIDField
             End Get
             Set(ByVal value As Integer)
                 organizationIDField = value
                 RaisePropertyChanged("LoOrganizationIDg")
             End Set
         End Property
    
         Private _clsOrganizationID As Integer
    
         Public Property clsOrganizationID As Integer
             Get
                 Return _clsOrganizationID
             End Get
             Set(ByVal value As Integer)
                 _clsOrganizationID = value
                 RaisePropertyChanged("clsOrganizationID")
    
             End Set
         End Property
    
         Public Event PropertyChanged As PropertyChangedEventHandler _
         Implements INotifyPropertyChanged.PropertyChanged
    
         Public Sub RaisePropertyChanged(ByVal propertyName As String)
             Dim handler As PropertyChangedEventHandler = PropertyChangedEvent
    
             If handler IsNot Nothing Then
                 handler(Me, New PropertyChangedEventArgs(propertyName))
             End If
         End Sub
    
         Public Overrides Function ToString() As String
             Return OrganizationID & " " & clsOrganizationID
         End Function
     End Class
    
     Public Class Organization
         Implements INotifyPropertyChanged
    
         Private organizationIDField As Integer
    
         Public Property OrganizationID As Integer
             Get
                 Return organizationIDField
             End Get
             Set(ByVal value As Integer)
                 organizationIDField = value
                 RaisePropertyChanged("OrganizationID")
             End Set
         End Property
    
         Private ocVendorsField As ObservableCollection(Of Vendor)
    
         Public Property OCVendors As ObservableCollection(Of Vendor)
             Get
                 Return ocVendorsField
             End Get
             Set(ByVal value As ObservableCollection(Of Vendor))
                 ocVendorsField = value
                 RaisePropertyChanged("OCVendors")
             End Set
         End Property
    
         Private _clsOrganizationID As Integer
    
         Public Property clsOrganizationID As Integer
             Get
                 Return _clsOrganizationID
             End Get
             Set(ByVal value As Integer)
                 _clsOrganizationID = value
                 RaisePropertyChanged("clsOrganizationID")
                 RaisePropertyChanged("IsVendor")
             End Set
         End Property
    
         Public ReadOnly Property IsVendor As Boolean
             Get
                 Dim vdr As Vendor = OCVendors.FirstOrDefault(Function(v) v.OrganizationID = clsOrganizationID)
    
                 Return vdr IsNot Nothing
    
             End Get
         End Property
    
         Public Event PropertyChanged As PropertyChangedEventHandler _
         Implements INotifyPropertyChanged.PropertyChanged
    
         Public Sub RaisePropertyChanged(ByVal propertyName As String)
             Dim handler As PropertyChangedEventHandler = PropertyChangedEvent
    
             If handler IsNot Nothing Then
                 handler(Me, New PropertyChangedEventArgs(propertyName))
             End If
         End Sub
     End Class
    
     Public Class Order
         Implements INotifyPropertyChanged
    
         Public Event PropertyChanged As PropertyChangedEventHandler _
         Implements INotifyPropertyChanged.PropertyChanged
    
         Public Sub RaisePropertyChanged(ByVal propertyName As String)
             Dim handler As PropertyChangedEventHandler = PropertyChangedEvent
    
             If handler IsNot Nothing Then
                 handler(Me, New PropertyChangedEventArgs(propertyName))
             End If
         End Sub
    
         Private nameField As String
         Private priceField As Double
         Private quantityField As Integer
    
         Public Property Name As String
             Get
                 Return nameField
             End Get
             Set(ByVal value As String)
    
                 If value IsNot nameField Then
                     nameField = value
                     RaisePropertyChanged("Name")
                 End If
             End Set
         End Property
    
         Public Property Price As Double
             Get
                 Return priceField
             End Get
             Set(ByVal value As Double)
    
                 If value <> priceField Then
                     priceField = value
                     RaisePropertyChanged("Price")
                     RaisePropertyChanged("TotalPrice")
                 End If
             End Set
         End Property
    
         Public Property Quantity As Integer
             Get
                 Return quantityField
             End Get
             Set(ByVal value As Integer)
    
                 If value <> quantityField Then
                     quantityField = value
                     RaisePropertyChanged("Quantity")
                 End If
             End Set
         End Property
    
         Public ReadOnly Property TotalPrice As Double
             Get
                 Return Price * Quantity
             End Get
         End Property
     End Class
 End Class

Demo Result:
123015-3.gif



If the response is helpful, please click "Accept Answer" and upvote it.
 Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread. 


3.gif (82.7 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.