C# 按内容对ListBoxItem进行排序,其中ListBoxItem是包含子项的StackPanel

C# 按内容对ListBoxItem进行排序,其中ListBoxItem是包含子项的StackPanel,c#,wpf,data-binding,C#,Wpf,Data Binding,我认为这是一种潜在的独特情况 我的列表框项目包括以下内容: 堆垛板 形象 列表项 将列表项和图像插入堆栈面板,然后将堆栈面板插入数组中每个项目的列表框 现在最具挑战性的部分是按照列表项的内容(文本)对内容进行排序,因为它是堆栈面板的子项。当然,StackPanel不包含内容成员,因此使用下面的代码失败 this.Items.SortDescriptions.Add(新系统.ComponentModel.SortDescription(“内容”), System.ComponentModel.

我认为这是一种潜在的独特情况

我的列表框项目包括以下内容:

  • 堆垛板
  • 形象
  • 列表项
列表项
图像
插入
堆栈面板
,然后将
堆栈面板
插入数组中每个项目的
列表框

现在最具挑战性的部分是按照
列表项的内容(文本)对内容进行排序,因为它是
堆栈面板的子项。当然,
StackPanel
不包含内容成员,因此使用下面的代码失败

this.Items.SortDescriptions.Add(新系统.ComponentModel.SortDescription(“内容”),
System.ComponentModel.ListSortDirection.升序);
所以我想,如果我将我的
StackPanel
的数据上下文设置为我的
ListItem
,那么它肯定会找到它

stackPanel.DataContext=this.Items;
然而,这也失败了

我正在用编程方式在代码隐藏中创建我的
列表项
,通过
Json.Net
加载数据

我的目标是根据项目内容从A-Z对项目进行排序。我更愿意保留我当前的实现(以编程方式创建数据),因为它使我能够更好地控制视觉效果。另外,它只有大约20行代码

列表项
的内容是
堆栈面板
时,是否可以使用
排序说明

多谢各位


PS:今天才开始使用WPF,但已经开发WinForms应用程序近2个月了。

WPF的方法是将您的列表框项目资源绑定到包含您的项目的可观察集合
然后,您将能够对您的可观察收集进行排序,以便:

CollectionViewSource.GetDefaultView(YourObservableCollection).SortDescriptions.Add(new SortDescription("PropertyToSort", ListSortDirection.Ascending));
这里有一个小项目突出了这一点:

XAML: 视图模型:
公共类视图模型:ObservableCollection
{
公共视图模型()
{
populateItems();
CollectionViewSource.GetDefaultView(this.SortDescriptions.Add)(新的SortDescription(“Item.Content”,ListSortDirection.升序));
}
私有void populateItems()
{
addOneItem(0,“零”);
新增一项(1,“一”);
增补一项(2,“两”);
增补一项(3,“三”);
增补项目(4,“四”);
}
私有void addOneItem(int img,字符串内容)
{
ListItem=新建ListItem();
item.Image=img;
item.item=newsomeitem{Content=Content};
增加(项目);
}
}
公共类列表项
{
公共int映像{get;set;}
公共SomeItem项{get;set;}
}
公共类项目
{
公共字符串内容{get;set;}
}

我冒昧地将您的“ListItem”重命名为“SomeItem”类,因为我不知道它是什么。
然后我创建了一个“ListItem”类,用于包含一个Image/SomeItem对(这是ListBox的组成部分)。
此外,我使用了int而不是实际图像,但这应该很容易更改。

下面是我在执行此代码时得到的屏幕截图:

希望这有帮助,祝你好运。


PS:如果您的项目值容易更改,请不要忘记在“SomeItem”和“ListItem”中实现INotifyPropertyChanged,否则更改不会在您的视图中更新。

WPF的方法是将您的ListBox项目资源绑定到包含您的项目的ObservableCollection
然后,您将能够对您的可观察收集进行排序,以便:

CollectionViewSource.GetDefaultView(YourObservableCollection).SortDescriptions.Add(new SortDescription("PropertyToSort", ListSortDirection.Ascending));
这里有一个小项目突出了这一点:

XAML: 视图模型:
公共类视图模型:ObservableCollection
{
公共视图模型()
{
populateItems();
CollectionViewSource.GetDefaultView(this.SortDescriptions.Add)(新的SortDescription(“Item.Content”,ListSortDirection.升序));
}
私有void populateItems()
{
addOneItem(0,“零”);
新增一项(1,“一”);
增补一项(2,“两”);
增补一项(3,“三”);
增补项目(4,“四”);
}
私有void addOneItem(int img,字符串内容)
{
ListItem=新建ListItem();
item.Image=img;
item.item=newsomeitem{Content=Content};
增加(项目);
}
}
公共类列表项
{
公共int映像{get;set;}
公共SomeItem项{get;set;}
}
公共类项目
{
公共字符串内容{get;set;}
}

我冒昧地将您的“ListItem”重命名为“SomeItem”类,因为我不知道它是什么。
然后我创建了一个“ListItem”类,用于包含一个Image/SomeItem对(这是ListBox的组成部分)。
此外,我使用了int而不是实际图像,但这应该很容易更改。

下面是我在执行此代码时得到的屏幕截图:

希望这有帮助,祝你好运。

PS:如果您的项目值容易更改,请不要忘记在“SomeItem”和“ListItem”中实现INotifyPropertyChanged,否则更改不会在您的视图中更新

当ListItem的内容是StackPanel时,是否可以使用SortDescriptions

不可以。您必须自己实现排序逻辑

对于从
列表框
属性返回的
项集合
,没有简单的方法可以应用自定义排序,因此您可以将项添加到
列表
并对其进行排序,而不是将项添加到此列表

您仍然可以像以前一样以编程方式创建数据

下面是一个例子:

代码:

public partial class MainWindow : Window
{
    private List<StackPanel> _theItems = new List<StackPanel>();
    public MainWindow()
    {
        InitializeComponent();

    //create the items:
        StackPanel sp1 = new StackPanel();
        ListBoxItem lbi1 = new ListBoxItem() { Content = "b" };
        Image img1 = new Image();
        sp1.Children.Add(lbi1);
        sp1.Children.Add(img1);
        _theItems.Add(sp1);

        StackPanel sp2 = new StackPanel();
        ListBoxItem lbi2 = new ListBoxItem() { Content = "a" };
        Image img2 = new Image();
        sp2.Children.Add(lbi2);
        sp2.Children.Add(img2);
        _theItems.Add(sp2);

        StackPanel sp3 = new StackPanel();
        ListBoxItem lbi3 = new ListBoxItem() { Content = "c" };
        Image img3 = new Image();
        sp3.Children.Add(lbi3);
        sp3.Children.Add(img3);
        _theItems.Add(sp3);

        //sort the items by the Content property of the ListBoxItem
        lb.ItemsSource = _theItems.OrderBy(x => x.Children.OfType<ListBoxItem>().FirstOrDefault().Content.ToString()).ToList();
    }
}
<ListBox x:Name="lb" />
公共部分类主窗口:窗口
{
私有列表=新列表();
公共主窗口()
{
初始化组件();
//创建项目:
s
public partial class MainWindow : Window
{
    private List<StackPanel> _theItems = new List<StackPanel>();
    public MainWindow()
    {
        InitializeComponent();

    //create the items:
        StackPanel sp1 = new StackPanel();
        ListBoxItem lbi1 = new ListBoxItem() { Content = "b" };
        Image img1 = new Image();
        sp1.Children.Add(lbi1);
        sp1.Children.Add(img1);
        _theItems.Add(sp1);

        StackPanel sp2 = new StackPanel();
        ListBoxItem lbi2 = new ListBoxItem() { Content = "a" };
        Image img2 = new Image();
        sp2.Children.Add(lbi2);
        sp2.Children.Add(img2);
        _theItems.Add(sp2);

        StackPanel sp3 = new StackPanel();
        ListBoxItem lbi3 = new ListBoxItem() { Content = "c" };
        Image img3 = new Image();
        sp3.Children.Add(lbi3);
        sp3.Children.Add(img3);
        _theItems.Add(sp3);

        //sort the items by the Content property of the ListBoxItem
        lb.ItemsSource = _theItems.OrderBy(x => x.Children.OfType<ListBoxItem>().FirstOrDefault().Content.ToString()).ToList();
    }
}
<ListBox x:Name="lb" />