6

I've been looking for a solution for my problem since yesterday. Im building a problem with MVVM pattern. I got two usercontrol, which are both containing a listbox.

The first usercontrol is called the SearchView which contains a listbox of project names, which the user can select and save to the applications local db.

enter image description here

When the selected projects are added a event is fired which notify the 2nd usercontrol which is named "ProjectView". This usercontrol simply shows which projects are saved locally. Seen at the picture below.

enter image description here

The problem is that i want to be able sort the listbox ascending by name in the projectview. So that if the user first add "Test Project 2" and afterwords add "Test Project 1" the "Test Project 1" is shown in the top of the listbox.

I have tried to use ICollectionView and ListCollectionView but im very really confused at the moment.

So now my Code looks like this, in the ProjectViewModel which needs to sort the listbox:

 public ProjectViewModel() {
     this.collectionView = CollectionViewSource.GetDefaultView(this.Projects);
 }

 private ObservableCollection<ProjectWrapper> _project = new ObservableCollection<ProjectWrapper>();
 public ObservableCollection<ProjectWrapper> Projects
 {
     get { return _project; }
     set
     {
         _project = value;
         OnPropertyChanged("Projects");
     }
 }

XAML code:

<UserControl.Resources>
    <CollectionViewSource x:Key="cvs" Source="{Binding Path=Projects}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="ProjectWrapper.Project.Name" />
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</UserControl.Resources>

<ListBox Name="ProjectsList" ItemsSource="{Binding Source={StaticResource cvs}}" SelectedItem="{Binding Path=SelectedProject}" HorizontalContentAlignment="Stretch" BorderThickness="0" Grid.Row="1" Grid.RowSpan="3" Margin="0,0.4,-0.2,27.8">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <TextBlock Text="{Binding Path=ProjectModel.Name}" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="3,2,0,0" />
                    <CheckBox  IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Right" VerticalAlignment="Center" Padding="0,2,5,0" Margin="0,2.5,0,0" />
                </DockPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Thanks in advance

RooKie-
  • 1,373
  • 3
  • 13
  • 24
  • 1
    Does this (http://stackoverflow.com/questions/1280704/how-can-i-sort-a-listbox-using-only-xaml-and-no-code-behind) shed any light for you? – Dr Herbie May 03 '13 at 10:47
  • Why don't you implement the IComparable interface in your projectwrapper class and then you do Projects.Sort() ? – Eduardo Brites May 03 '13 at 10:55
  • Yeah i been looking at that question, and tried the same. But it's not sorting my list properly. If i added Project 3, and then Proejct 2 it's sorted correct --> Project 1, then Project 3. But then when Project 2 is added which should be in the middel of the two projects, it's getting added at the top of til listbox. – RooKie- May 03 '13 at 11:04
  • @EduardoBrites where does `System.Collections.ObjectModel.ObservableCollection` have a `Sort()` methode? – WiiMaxx May 03 '13 at 11:04
  • 1
    How about binding the `CheckBox` to a `IsAdded` property on the `ProjectWrapper`. As your event is caught in the second view model I'd clear the list completely and rebuild it like `AddedProjects = OriginalProjects.Where(p => p.IsAdded).OrderBy(p => p.Name)`. – Michael Schnerring May 03 '13 at 11:12

3 Answers3

2

call this when you adding element to the Projects list

Projects = new ObservableCollection<ProjectWrapper>(Projects.OrderBy(x => x.Name));
Chamika Sandamal
  • 23,565
  • 5
  • 63
  • 86
  • This answer works really great! Thanks alot! I got a little followup question. Do you know what could be done if you have a number in the end of the project name. Let's say I have the following projects: Test Project 1 - 10. As it is now the sorting is like this: Test Project 1, Test Project 10 and Test Project 2 - 9. – RooKie- May 03 '13 at 11:27
  • try this for your followup question. http://stackoverflow.com/questions/6396378/c-sharp-linq-orderby-numbers-that-are-string-and-you-cannot-convert-them-to-int – Chamika Sandamal May 03 '13 at 20:08
0

you can use Linq

Sample:

        var coll = new ObservableCollection<myItem>();
        coll.Add(new myItem() { Id = 0, Name = "zz" });
        coll.Add(new myItem() { Id = 3, Name = "bb" });
        coll.Add(new myItem() { Id = 1, Name = "aa" });

        var sortedById = from item in coll
                         orderby item.Id
                         select item;

        var sortedByName = from item in coll
                         orderby item.Name
                         select item;

        coll = new ObservableCollection<myItem>(sortedById);
        coll = new ObservableCollection<myItem>(sortedByName);

class myItem
{
    public int Id { get; set; }
    public string Name { get; set; }
}
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
0

It should be enough when you change the SortDescription in your XAML to:

<scm:SortDescription PropertyName="ProjectModel.Name" />

Since you want to sort by the name of the project, where i think it is the same as you use in the binding of the TextBlock {Binding Path=ProjectModel.Name}

Jehof
  • 34,674
  • 10
  • 123
  • 155