简体   繁体   English

按内容对ListBox项进行排序,其中ListBoxItem是具有子级的StackPanel

[英]Sort ListBox items by Content where ListBoxItem is a StackPanel with children

I have what I believe to be a potentially unique situation. 我认为这是一个潜在的独特情况。

My ListBox items consist of the following: 我的列表框项目包括以下内容:

  • StackPanel StackPanel
  • Image 图片
  • ListItem 项目清单

The ListItem and Image are inserted into the StackPanel , then the StackPanel is the inserted into the ListBox for each item in the array. ListItemImage插入到StackPanel ,然后将StackPanel插入到数组中每个项目的ListBox中。

Now the challenging part comes in sorting the content by the ListItem 's Content (text) as it's a child of the StackPanel . 现在,具有挑战性的部分是按照ListItem的Content(文本)对内容进行排序,因为它是StackPanel的子级。 Naturally, the StackPanel does not contain a Content member, so using the below code fails. 自然, StackPanel不包含Content成员,因此使用以下代码失败。

this.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("Content",
        System.ComponentModel.ListSortDirection.Ascending));

So I figured, what if I set my StackPanel 's data context to my ListItem , then surely it will find it. 所以我想,如果我将StackPanel的数据上下文设置为ListItem ,那肯定会找到它。

stackPanel.DataContext = this.Items;

However, that also fails. 但是,这也失败了。

I'm creating my ListItems programatically in the code behind, via data that is loaded in via Json.Net . 我正在通过背后的代码以编程方式通过通过Json.Net加载的数据来创建ListItems

My goal here is to sort the items from AZ, based on the Items Content. 我的目标是根据项目内容对AZ中的项目进行排序。 I would prefer to keep my current implementation (creating the data programatically) as it gives me more control over the visuals. 我希望保留当前的实现(以编程方式创建数据),因为它可以使我更好地控制视觉效果。 Plus, it's only about 20 lines of code. 另外,它仅约20行代码。

Is it possible to use SortDescriptions when the ListItem 's content is a StackPanel ? ListItem的内容为StackPanel时,可以使用SortDescriptions吗?

Thank you 谢谢

PS: Only started with WPF today, but have been developing WinForms apps for nearly 2 months. PS:今天才从WPF开始,但是已经开发了将近两个月的WinForms应用程序。

The WPF way to do it would be to bind your ListBox ItemsSource to an ObservableCollection containing your items. WPF的实现方法是将ListBox ItemsSource绑定到包含您的项目的ObservableCollection。
You would then be able to sort your observableCollection liks so : 然后,您将能够对您的observableCollection排序,如下所示:

CollectionViewSource.GetDefaultView(YourObservableCollection).SortDescriptions.Add(new SortDescription("PropertyToSort", ListSortDirection.Ascending));

Here is a small project that highlights this : 这是一个突出这一点的小项目:

XAML : XAML:

<Window x:Class="stackPanelTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:stackPanelTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

    <Grid>
        <ListBox ItemsSource="{Binding Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Image}" />
                        <TextBlock Text="{Binding Item.Content}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

</Window>

Code Behind : 背后的代码:

public partial class MainWindow : Window
{
    public ViewModel Items { get; set; } = new ViewModel();
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

ViewModel : ViewModel:

public class ViewModel : ObservableCollection<ListItem>
{
    public ViewModel()
    {
        populateItems();
        CollectionViewSource.GetDefaultView(this).SortDescriptions.Add(new SortDescription("Item.Content", ListSortDirection.Ascending));
    }

    private void populateItems()
    {
        addOneItem(0, "zero");
        addOneItem(1, "one");
        addOneItem(2, "two");
        addOneItem(3, "three");
        addOneItem(4, "four");
    }

    private void addOneItem(int img, string content)
    {
        ListItem item = new ListItem();
        item.Image = img;
        item.Item = new SomeItem { Content = content };

        Add(item);
    }
}

public class ListItem
{
    public int Image { get; set; }
    public SomeItem Item { get; set; }
}

public class SomeItem
{
    public string Content { get; set; }
}


I took the liberty of renaming your "ListItem" into a "SomeItem" class because I didn't know what it was. 我冒昧地将您的“ ListItem”重命名为“ SomeItem”类,因为我不知道它是什么。
Then I made a "ListItem" class which is used to contain a Image/SomeItem pair (which is what your ListBox is composed of). 然后,我制作了一个“ ListItem”类,该类用于包含Image / SomeItem对(这是您的ListBox组成的)。
Also I used an int instead of an actual image but that should be easily changable. 我也使用int而不是实际图像,但是应该可以轻松更改。

Here's a screenshot of what I get when executing this code : 这是执行此代码时得到的屏幕截图: 列表框屏幕截图

Hope this helps, good luck. 希望这有帮助,祝你好运。

PS : if your items values are susceptible to change, don't forget to implement INotifyPropertyChanged in "SomeItem" and "ListItem", otherwise the change won't be updated in your view. PS:如果您的项目值易于更改,请不要忘记在“ SomeItem”和“ ListItem”中实现INotifyPropertyChanged,否则更改不会在您的视图中更新。

Is it possible to use SortDescriptions when the ListItem's content is a StackPanel ? 当ListItem的内容是StackPanel时,可以使用SortDescriptions吗?

No. You will have to implement the sorting logic yourself. 否。您将必须自己实现排序逻辑。

There is no easy way to apply custom sorting to the ItemCollection that is returned from the Items property of the ListBox so instead of adding items to this one you could add the items to a List<StackPanel> and sort this one. 没有简单的方法将自定义排序应用于从ListBoxItems属性返回的ItemCollection ,因此可以将项目添加到List<StackPanel>并对其进行排序,而不是向该项目添加项目。

You could still create the data programatically just as before. 您仍然可以像以前一样以编程方式创建数据。

Here is an example for you: 这是给你的一个例子:

Code: 码:

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

XAML: XAML:

<ListBox x:Name="lb" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM