使用MVVM在按钮被点击时对列表框进行排序

6
自昨天开始,我一直在寻找解决方案。我正在使用MVVM模式构建一个问题。
我有两个用户控件,它们都包含一个列表框。
第一个用户控件称为SearchView,其中包含一个项目名称列表框,用户可以选择并保存到应用程序的本地数据库中。
当添加选定的项目时,会触发一个事件,通知名为“ProjectView”的第二个用户控件。该用户控件只显示本地保存的项目,如下图所示。
问题是,我想能够按名称升序排序项目视图中的列表框。这样,如果用户首先添加“Test Project 2”,然后再添加“Test Project 1”,则“Test Project 1”将显示在列表框的顶部。
我尝试使用ICollectionView和ListCollectionView,但目前非常困惑。
因此,现在我的代码看起来像这样,在需要对列表框进行排序的ProjectViewModel中:
 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代码:

<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>

非常感谢您的提前帮助。


1
这个(https://dev59.com/BnM_5IYBdhLWcg3wq1GF)对你有帮助吗? - Dr Herbie
为什么不在你的ProjectWrapper类中实现IComparable接口,然后执行Projects.Sort()呢? - Eduardo Brites
是的,我一直在看那个问题,并尝试着做同样的事情。但它没有正确地对我的列表进行排序。如果我添加了Project 3,然后是Project 2,它会正确地排序--> Project 1,然后是Project 3。但是当添加应该在这两个项目中间的Project 2时,它被添加到了列表框的顶部。 - RooKie-
@EduardoBrites System.Collections.ObjectModel.ObservableCollection 这个类中在哪里可以找到 Sort() 方法? - WiiMaxx
1
CheckBoxProjectWrapper 上的 IsAdded 属性绑定,如何呢?由于您的事件在第二个视图模型中被捕获,我会清除列表并重新构建它,例如 AddedProjects = OriginalProjects.Where(p => p.IsAdded).OrderBy(p => p.Name) - Michael Schnerring
3个回答

2

当你添加元素到Projects列表时,请调用此函数。

Projects = new ObservableCollection<ProjectWrapper>(Projects.OrderBy(x => x.Name));

这个答案非常好!非常感谢!我有一个小的后续问题。如果项目名称末尾有一个数字,你知道该怎么办吗?比如说我有以下项目:测试项目1-10。现在排序是这样的:测试项目1、测试项目10和测试项目2-9。 - RooKie-
尝试在您的后续问题中使用此链接:https://dev59.com/L2w15IYBdhLWcg3wy-zO。 - Chamika Sandamal

0

你可以使用 Linq

示例:

        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; }
}

0

当您在XAML中更改SortDescription时,应该足够了:

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

由于您想按项目名称排序,我认为它与您在 TextBlock 绑定中使用的 {Binding Path=ProjectModel.Name} 相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接