Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. WPF
  4. Reference to parent collection

Reference to parent collection

Scheduled Pinned Locked Moved WPF
wpfquestioncsharphelplounge
6 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    ausadmin
    wrote on last edited by
    #1

    Apologies in advance, I suspect there may be an obvious answer to this, but I have searched these forums and google and not really been able to determine the solution. This is for a WPF application, but I think it is a more general programming question. We have an ObservableCollection(of T), where we need do do some validation of the member object, T. One of the rules is that a property of T (say name) cannot already exist in the collection. Our validation class is instantiated from the xaml, so I don't know of any way to pass in the reference to the ObservableCollection. However, this is needed to be able to step through the collection, to see if name has already been used, and report an error (if needed). One solution I can see is that the class T could have a property which is an ObservableCollection of T, and then you pass the parent collection into the member object. I think this will solve the issues, but something says to me this would be bad practise... Can anyone clarify whether this will cause errors or should be avoided? Can anyone suggest an alternative? More specifically, say we define Person

    Public Class Person
    Public Sub New(ByVal Name As String, ByVal People As ObservableCollection(Of Person))
    ...
    End Sub

    Public Property Name() As String
        ...
    End Property
    
    Public Property People() As ObservableCollection(Of Person)
        ...
    End Property
    

    End Class

    Then elsewhere make a collection of Person

        Dim MemberList As New ObservableCollection(Of Person)
        MemberList.Add(New Person("John", MemberList))
        MemberList.Add(New Person("Fred", MemberList))
        MemberList.Add(New Person("Jane", MemberList))
        MemberList.Add(New Person("Andrew", MemberList))
    

    Then we can bind say a WPF DataGrid to MemberList, and use validation to check our rule, to check that the Person name has not already been used in the ObservableCollection(of Person) - ie MemberList. The approach here will work, but I am concerned that there might be underlying problems - some circular reference or something (or else just not good practise). Thanks for any suggestions. Tim

    P 1 Reply Last reply
    0
    • A ausadmin

      Apologies in advance, I suspect there may be an obvious answer to this, but I have searched these forums and google and not really been able to determine the solution. This is for a WPF application, but I think it is a more general programming question. We have an ObservableCollection(of T), where we need do do some validation of the member object, T. One of the rules is that a property of T (say name) cannot already exist in the collection. Our validation class is instantiated from the xaml, so I don't know of any way to pass in the reference to the ObservableCollection. However, this is needed to be able to step through the collection, to see if name has already been used, and report an error (if needed). One solution I can see is that the class T could have a property which is an ObservableCollection of T, and then you pass the parent collection into the member object. I think this will solve the issues, but something says to me this would be bad practise... Can anyone clarify whether this will cause errors or should be avoided? Can anyone suggest an alternative? More specifically, say we define Person

      Public Class Person
      Public Sub New(ByVal Name As String, ByVal People As ObservableCollection(Of Person))
      ...
      End Sub

      Public Property Name() As String
          ...
      End Property
      
      Public Property People() As ObservableCollection(Of Person)
          ...
      End Property
      

      End Class

      Then elsewhere make a collection of Person

          Dim MemberList As New ObservableCollection(Of Person)
          MemberList.Add(New Person("John", MemberList))
          MemberList.Add(New Person("Fred", MemberList))
          MemberList.Add(New Person("Jane", MemberList))
          MemberList.Add(New Person("Andrew", MemberList))
      

      Then we can bind say a WPF DataGrid to MemberList, and use validation to check our rule, to check that the Person name has not already been used in the ObservableCollection(of Person) - ie MemberList. The approach here will work, but I am concerned that there might be underlying problems - some circular reference or something (or else just not good practise). Thanks for any suggestions. Tim

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      Tim What you are after is an ObservableDictionary. The good Dr WPF has a sample implementation of one here[^].

      "WPF has many lovers. It's a veritable porn star!" - Josh Smith

      As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

      My blog | My articles | MoXAML PowerToys | Onyx

      A 1 Reply Last reply
      0
      • P Pete OHanlon

        Tim What you are after is an ObservableDictionary. The good Dr WPF has a sample implementation of one here[^].

        "WPF has many lovers. It's a veritable porn star!" - Josh Smith

        As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

        My blog | My articles | MoXAML PowerToys | Onyx

        A Offline
        A Offline
        ausadmin
        wrote on last edited by
        #3

        Pete, Thank you for your reply. I have read the article you refer to ("The Observable Dictionary Sample" - correct?), however I am not clear on how this might solve the problem. I need to explain a bit more about the scenario. We have a WPF DataGrid bound to our ObservableCollection - this works really well. I am now trying to handle validation as a user makes changes. Where the valiadtion can be based solely on the content of the member object (ie the data in the row, e.g. ensure an age is between 5 and 50) - no problem, use the ValidationRule approach as is well documented. What I am having trouble with is the scenario where a value must be checked against all others in the ObservableCollection - I don't know of any way to make the ValidationRule class know about the parent collection. So I think this problem will exist, whether we are using ObservableCollection or ObservableDictionary. Please correct me if I have misunderstood your post. Maybe I am missing something, on how we can pass in the parent collection, to the ValidationRule instance (ie NameRule) that is doing the validation. Our xaml is

                <toolkit:DataGridTextColumn  Header="Name" Width="100"  >
                    <toolkit:DataGridTextColumn.Binding  >
                        <Binding Path="Name" >
                            <Binding.ValidationRules>
                                <local:NameRule ValidationStep="UpdatedValue"/> 
                            </Binding.ValidationRules>
                        </Binding>
                    </toolkit:DataGridTextColumn.Binding>
                </toolkit:DataGridTextColumn>
        

        There could be several ways to solve this, outside of the DataGrid, but I am trying to find the best method which utilises the WPF way of doing validation. BTW, I have reviewed the excellent article "WPF DataGrid Practical Examples" [^], and this addresses data validation. However the example provided is based on a DataTable as itemssource (in which case you can refer back to the DataTable), and it seems there should also be a way to use ObservableCollection as the itemssource. Any further suggestions would be appreciated. Tim

        P 1 Reply Last reply
        0
        • A ausadmin

          Pete, Thank you for your reply. I have read the article you refer to ("The Observable Dictionary Sample" - correct?), however I am not clear on how this might solve the problem. I need to explain a bit more about the scenario. We have a WPF DataGrid bound to our ObservableCollection - this works really well. I am now trying to handle validation as a user makes changes. Where the valiadtion can be based solely on the content of the member object (ie the data in the row, e.g. ensure an age is between 5 and 50) - no problem, use the ValidationRule approach as is well documented. What I am having trouble with is the scenario where a value must be checked against all others in the ObservableCollection - I don't know of any way to make the ValidationRule class know about the parent collection. So I think this problem will exist, whether we are using ObservableCollection or ObservableDictionary. Please correct me if I have misunderstood your post. Maybe I am missing something, on how we can pass in the parent collection, to the ValidationRule instance (ie NameRule) that is doing the validation. Our xaml is

                  <toolkit:DataGridTextColumn  Header="Name" Width="100"  >
                      <toolkit:DataGridTextColumn.Binding  >
                          <Binding Path="Name" >
                              <Binding.ValidationRules>
                                  <local:NameRule ValidationStep="UpdatedValue"/> 
                              </Binding.ValidationRules>
                          </Binding>
                      </toolkit:DataGridTextColumn.Binding>
                  </toolkit:DataGridTextColumn>
          

          There could be several ways to solve this, outside of the DataGrid, but I am trying to find the best method which utilises the WPF way of doing validation. BTW, I have reviewed the excellent article "WPF DataGrid Practical Examples" [^], and this addresses data validation. However the example provided is based on a DataTable as itemssource (in which case you can refer back to the DataTable), and it seems there should also be a way to use ObservableCollection as the itemssource. Any further suggestions would be appreciated. Tim

          P Offline
          P Offline
          Pete OHanlon
          wrote on last edited by
          #4

          The reason I suggested an ObservableDictionary is that it, by default, solves the problem where you can't have an entry with the same key name. One thing I would say - move your validation out of the binding into a ViewModel, it's a lot easier to test and you can make your rules a lot more flexible, especially as you would have full programattic access to your ObservableCollection.

          "WPF has many lovers. It's a veritable porn star!" - Josh Smith

          As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

          My blog | My articles | MoXAML PowerToys | Onyx

          A 1 Reply Last reply
          0
          • P Pete OHanlon

            The reason I suggested an ObservableDictionary is that it, by default, solves the problem where you can't have an entry with the same key name. One thing I would say - move your validation out of the binding into a ViewModel, it's a lot easier to test and you can make your rules a lot more flexible, especially as you would have full programattic access to your ObservableCollection.

            "WPF has many lovers. It's a veritable porn star!" - Josh Smith

            As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

            My blog | My articles | MoXAML PowerToys | Onyx

            A Offline
            A Offline
            ausadmin
            wrote on last edited by
            #5

            Pete, Thanks for the suggestion of using a ViewModel. I am a big fan of using ViewModel and have made extensive use of this pattern in our project (where it fits). I found your article "Action based ViewModel and Model validation." and Josh Smith's article "Using a ViewModel to Provide Meaningful Validation Error Messages" on this approach (I assume that is what you meant), and have now modified the project accordingly. So the original class was ATUser and I defined a new UserViewModel class which wraps ATUser. I have been able to achieve the validation (and it works nicely), however I am still not sure I am following good programming practise (really my original question), because I found it essential to pass a reference to the ObservableCollection (container collection), into each UserViewModel member, so the member could find out if the user name had already been used. So a snippet of UserViewModel is

            Public Class UserViewModel
            Implements INotifyPropertyChanged
            Implements IDataErrorInfo

            Private \_user As ATUser
            Private \_containerCollection As AUSObservableCollection(Of UserViewModel)
            
            Public Sub New(ByRef User As ATUser, \_
                           ByRef ContainerCollection As AUSObservableCollection(Of UserViewModel))
                \_user = User
                \_containerCollection = ContainerCollection
                \_username = \_user.Username
            End Sub
            
            'lines removed
            Default Public ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item
                Get
                    Select Case propertyName
                        Case "Username"
                        'logic to determine if Username is valid, which involves searching through \_containerCollection 
                    End Select
                End Get
            End Property
            

            End Class

            So I believe I have achieved the goals of using the ViewModel, which include improved control over Data Validation. However I'm not sure I addressed my original concern - which is holding a reference to the containing collection within the member object itself.... Could you comment on whether I have missed the point / whether there is a more acceptable way to solve this / whether the reference to the containing collection is OK? Just to restate, in order for a UserViewModel to validate the Username property, it needs to access the containing collection, in order to see if the name has already been used. From the Data Validation point of view, I could have achieved the same by implementing IDataErrorInfo on the ATUser class, and simpl

            A 1 Reply Last reply
            0
            • A ausadmin

              Pete, Thanks for the suggestion of using a ViewModel. I am a big fan of using ViewModel and have made extensive use of this pattern in our project (where it fits). I found your article "Action based ViewModel and Model validation." and Josh Smith's article "Using a ViewModel to Provide Meaningful Validation Error Messages" on this approach (I assume that is what you meant), and have now modified the project accordingly. So the original class was ATUser and I defined a new UserViewModel class which wraps ATUser. I have been able to achieve the validation (and it works nicely), however I am still not sure I am following good programming practise (really my original question), because I found it essential to pass a reference to the ObservableCollection (container collection), into each UserViewModel member, so the member could find out if the user name had already been used. So a snippet of UserViewModel is

              Public Class UserViewModel
              Implements INotifyPropertyChanged
              Implements IDataErrorInfo

              Private \_user As ATUser
              Private \_containerCollection As AUSObservableCollection(Of UserViewModel)
              
              Public Sub New(ByRef User As ATUser, \_
                             ByRef ContainerCollection As AUSObservableCollection(Of UserViewModel))
                  \_user = User
                  \_containerCollection = ContainerCollection
                  \_username = \_user.Username
              End Sub
              
              'lines removed
              Default Public ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item
                  Get
                      Select Case propertyName
                          Case "Username"
                          'logic to determine if Username is valid, which involves searching through \_containerCollection 
                      End Select
                  End Get
              End Property
              

              End Class

              So I believe I have achieved the goals of using the ViewModel, which include improved control over Data Validation. However I'm not sure I addressed my original concern - which is holding a reference to the containing collection within the member object itself.... Could you comment on whether I have missed the point / whether there is a more acceptable way to solve this / whether the reference to the containing collection is OK? Just to restate, in order for a UserViewModel to validate the Username property, it needs to access the containing collection, in order to see if the name has already been used. From the Data Validation point of view, I could have achieved the same by implementing IDataErrorInfo on the ATUser class, and simpl

              A Offline
              A Offline
              ausadmin
              wrote on last edited by
              #6

              Another alternative I have discovered is to use a shared member property of a Helper object to hold the collection that needs to be searched. I can define this as follows:

              Public Class ATBusinessInfoHelper

              Private Shared \_userContainer As AUSObservableCollection(Of ATUser)
              
              Public Shared Property UserContainer() As AUSObservableCollection(Of ATUser)
                  Get
                      If \_userContainer Is Nothing Then
                          Throw New AUSException("UserContainer has not been defined")
                      Else
                          Return \_userContainer
                      End If
                  End Get
                  Set(ByVal value As AUSObservableCollection(Of ATUser))
                      \_userContainer = value
                  End Set
              End Property
              

              End Class

              Then in the IDataErrorInfo validation logic, I can step through ATBusinessInfoHelper.UserContainer to see if there is a conflict with an existing name. Would this be a valid approach to take? Thanks for any advice, Tim

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups