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
  1. Home
  2. General Programming
  3. WPF
  4. Sorting a listbox when SortDescription won't cut it [modified]

Sorting a listbox when SortDescription won't cut it [modified]

Scheduled Pinned Locked Moved WPF
questionalgorithmsdebuggingannouncement
7 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.
  • J Offline
    J Offline
    Jean Louis Leroy
    wrote on last edited by
    #1

    Hello, I have a listbox bound to a DataView showing rows from a table (ReportingUser) in a typed DataSet. The table has a DataRelation to another table (Reporting). Hence the (typed) row objects have a ReportingRow property that refers to the corresponding row in the related table. Each row is displayed using text from the Reporting related table:

    I would like to sort the listbox by ReportingName as well. I have been struggling with this for two days. None of the solutions I found via Google work. They include: 1/ Use a SortDescription. But that mechanism doesn't seem capable of following property chains, unlike DisplayMemberPath. 2/ Grab the defaultView and set the Sort property. But the mechanism is string-based and gives access to the row's columns only. 3/ Cast the defaultView to a ListCollectionView and set a custom IComparer. But the cast fails. I also had an idea: use a partial class definition to add a new property, to be used in SortDescriptions:

      partial class ReportingUserRow
      {
        public string ReportingName
        {
          get
          {
            return ReportingRow.ReportingName;
          }
        }
      }
    

    Alas when I try to use it in either DisplayMemberPath or SortDescription, I get an exception that the property doesn't exist. UPDATE: I can use my property in DisplayMemberPath like this: DisplayMemberPath="Row.ReportingName" Which opens the question: using the debugger I see that my listbox contains a DataView that contains DataRowView objects which in turn contain a reference to a row object (of type ReportingUserRow). How does DataRowView find out what properties are available on a ReportingUserRow ? Why does it find the columns and not my extra property ?

    modified on Wednesday, April 13, 2011 6:03 AM

    S J 2 Replies Last reply
    0
    • J Jean Louis Leroy

      Hello, I have a listbox bound to a DataView showing rows from a table (ReportingUser) in a typed DataSet. The table has a DataRelation to another table (Reporting). Hence the (typed) row objects have a ReportingRow property that refers to the corresponding row in the related table. Each row is displayed using text from the Reporting related table:

      I would like to sort the listbox by ReportingName as well. I have been struggling with this for two days. None of the solutions I found via Google work. They include: 1/ Use a SortDescription. But that mechanism doesn't seem capable of following property chains, unlike DisplayMemberPath. 2/ Grab the defaultView and set the Sort property. But the mechanism is string-based and gives access to the row's columns only. 3/ Cast the defaultView to a ListCollectionView and set a custom IComparer. But the cast fails. I also had an idea: use a partial class definition to add a new property, to be used in SortDescriptions:

        partial class ReportingUserRow
        {
          public string ReportingName
          {
            get
            {
              return ReportingRow.ReportingName;
            }
          }
        }
      

      Alas when I try to use it in either DisplayMemberPath or SortDescription, I get an exception that the property doesn't exist. UPDATE: I can use my property in DisplayMemberPath like this: DisplayMemberPath="Row.ReportingName" Which opens the question: using the debugger I see that my listbox contains a DataView that contains DataRowView objects which in turn contain a reference to a row object (of type ReportingUserRow). How does DataRowView find out what properties are available on a ReportingUserRow ? Why does it find the columns and not my extra property ?

      modified on Wednesday, April 13, 2011 6:03 AM

      S Offline
      S Offline
      SledgeHammer01
      wrote on last edited by
      #2
      1. I'm pretty sure that doesn't work... the implementation pretty much reflects on the current type and gets a property named "x". "Row.ReportingRow.ReportingName" is not the name of a valid property. 3) Should work just fine. I do it all over the place. How are you getting the default view? Show code. If the cast is failing, what IS GetDefaultView() returning?
      J 1 Reply Last reply
      0
      • S SledgeHammer01
        1. I'm pretty sure that doesn't work... the implementation pretty much reflects on the current type and gets a property named "x". "Row.ReportingRow.ReportingName" is not the name of a valid property. 3) Should work just fine. I do it all over the place. How are you getting the default view? Show code. If the cast is failing, what IS GetDefaultView() returning?
        J Offline
        J Offline
        Jean Louis Leroy
        wrote on last edited by
        #3

        Relevant lines from Window_Loaded:

          dataset = new DNLMHDataSet(); // a designer-generated typed dataset
          reportingUserAdapter = new ReportingUserTableAdapter();
          reportingUserAdapter.Fill(dataset.ReportingUser);
          listBoxSelectedReporting.DataContext = dataset;
        

        I run my program and make it break. In the Immediate window:

        ?System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)
        {System.Windows.Data.BindingListCollectionView}
        [System.Windows.Data.BindingListCollectionView]: {System.Windows.Data.BindingListCollectionView}
        CanFilter: false
        CanGroup: true
        CanSort: false
        Culture: null
        CurrentItem: {System.Data.DataViewManagerListItemTypeDescriptor}
        CurrentPosition: 0
        Filter: null
        GroupDescriptions: {System.Collections.ObjectModel.ObservableCollection}
        Groups: null
        IsCurrentAfterLast: false
        IsCurrentBeforeFirst: false
        IsEmpty: false
        SortDescriptions: {System.ComponentModel.SortDescriptionCollection.EmptySortDescriptionCollection}
        SourceCollection: {System.Data.DataViewManager}

        Let's try the cast:

        ?(ListCollectionView)System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)
        Cannot cast 'System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)' (which has an actual type of 'System.Windows.Data.BindingListCollectionView') to 'System.Windows.Data.ListCollectionView'

        When I look at the MS headers I see that both ListCollectionView and BindingListCollectionView derive from CollectionView. They're siblings, hence no cast...

        S 1 Reply Last reply
        0
        • J Jean Louis Leroy

          Hello, I have a listbox bound to a DataView showing rows from a table (ReportingUser) in a typed DataSet. The table has a DataRelation to another table (Reporting). Hence the (typed) row objects have a ReportingRow property that refers to the corresponding row in the related table. Each row is displayed using text from the Reporting related table:

          I would like to sort the listbox by ReportingName as well. I have been struggling with this for two days. None of the solutions I found via Google work. They include: 1/ Use a SortDescription. But that mechanism doesn't seem capable of following property chains, unlike DisplayMemberPath. 2/ Grab the defaultView and set the Sort property. But the mechanism is string-based and gives access to the row's columns only. 3/ Cast the defaultView to a ListCollectionView and set a custom IComparer. But the cast fails. I also had an idea: use a partial class definition to add a new property, to be used in SortDescriptions:

            partial class ReportingUserRow
            {
              public string ReportingName
              {
                get
                {
                  return ReportingRow.ReportingName;
                }
              }
            }
          

          Alas when I try to use it in either DisplayMemberPath or SortDescription, I get an exception that the property doesn't exist. UPDATE: I can use my property in DisplayMemberPath like this: DisplayMemberPath="Row.ReportingName" Which opens the question: using the debugger I see that my listbox contains a DataView that contains DataRowView objects which in turn contain a reference to a row object (of type ReportingUserRow). How does DataRowView find out what properties are available on a ReportingUserRow ? Why does it find the columns and not my extra property ?

          modified on Wednesday, April 13, 2011 6:03 AM

          J Offline
          J Offline
          Jean Louis Leroy
          wrote on last edited by
          #4

          I tried yet another approach: sort the rows at the source, using this code:

            dataset.ReportingUser.OrderBy(
              row =>
              {
                System.Diagnostics.Trace.WriteLine("\*\*\* called \*\*\*");
                return row.ReportingRow.ReportingName;
              });
          

          I tried putting it before and after the call to reportingUserAdapter.Fill(dataset.ReportingUser) but it is never called. Feeling despaired... :sigh:

          1 Reply Last reply
          0
          • J Jean Louis Leroy

            Relevant lines from Window_Loaded:

              dataset = new DNLMHDataSet(); // a designer-generated typed dataset
              reportingUserAdapter = new ReportingUserTableAdapter();
              reportingUserAdapter.Fill(dataset.ReportingUser);
              listBoxSelectedReporting.DataContext = dataset;
            

            I run my program and make it break. In the Immediate window:

            ?System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)
            {System.Windows.Data.BindingListCollectionView}
            [System.Windows.Data.BindingListCollectionView]: {System.Windows.Data.BindingListCollectionView}
            CanFilter: false
            CanGroup: true
            CanSort: false
            Culture: null
            CurrentItem: {System.Data.DataViewManagerListItemTypeDescriptor}
            CurrentPosition: 0
            Filter: null
            GroupDescriptions: {System.Collections.ObjectModel.ObservableCollection}
            Groups: null
            IsCurrentAfterLast: false
            IsCurrentBeforeFirst: false
            IsEmpty: false
            SortDescriptions: {System.ComponentModel.SortDescriptionCollection.EmptySortDescriptionCollection}
            SourceCollection: {System.Data.DataViewManager}

            Let's try the cast:

            ?(ListCollectionView)System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)
            Cannot cast 'System.Windows.Data.CollectionViewSource.GetDefaultView(listBoxSelectedReporting.DataContext)' (which has an actual type of 'System.Windows.Data.BindingListCollectionView') to 'System.Windows.Data.ListCollectionView'

            When I look at the MS headers I see that both ListCollectionView and BindingListCollectionView derive from CollectionView. They're siblings, hence no cast...

            S Offline
            S Offline
            SledgeHammer01
            wrote on last edited by
            #5

            So, um... didn't you just answer your own question??? :doh: :doh: :doh: In your particular case, you have a BindingListCollectionView, not a ListCollectionView. Simply cast the GetDefaultView() return into a BindingListCollectionView object and use that. GetDefaultView() actually returns an ICollectionView object. So, it is possible to get ANYTHING implementing the ICollectionView interface (like BindingListCollectionView in this case). BindingListCollectionView implements everything you need. Like Comparer for example ;)

            J 1 Reply Last reply
            0
            • S SledgeHammer01

              So, um... didn't you just answer your own question??? :doh: :doh: :doh: In your particular case, you have a BindingListCollectionView, not a ListCollectionView. Simply cast the GetDefaultView() return into a BindingListCollectionView object and use that. GetDefaultView() actually returns an ICollectionView object. So, it is possible to get ANYTHING implementing the ICollectionView interface (like BindingListCollectionView in this case). BindingListCollectionView implements everything you need. Like Comparer for example ;)

              J Offline
              J Offline
              Jean Louis Leroy
              wrote on last edited by
              #6

              SledgeHammer01 wrote:

              BindingListCollectionView implements everything you need. Like Comparer for example

              ...but the Comparer property is read-only :sigh: And it has the SortDescriptions but it's useless for my purpose... X|

              S 1 Reply Last reply
              0
              • J Jean Louis Leroy

                SledgeHammer01 wrote:

                BindingListCollectionView implements everything you need. Like Comparer for example

                ...but the Comparer property is read-only :sigh: And it has the SortDescriptions but it's useless for my purpose... X|

                S Offline
                S Offline
                SledgeHammer01
                wrote on last edited by
                #7

                Oh right... sorry, yeah, I forgot some of the view classes randomly make useful properties read-only :). Ok, well, then there are a few ways you can proceed. 1) You are getting BindingListCollectionView because you are binding to a source that implements IBindingList. So you can repackage the data in something different like an ObservableCollection, etc. 2) You can try wrap your source in a CollectionViewSource. CollectionViewSource requires the source to implement IEnumerable which should work for you. #2 is probably easier, but if that doesn't work, you'll have to do #1 :). It kind of makes sense that what you are trying to do is not really supported directly.

                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