C# 自排序列表框

C# 自排序列表框,c#,winforms,sorting,listbox,bindinglist,C#,Winforms,Sorting,Listbox,Bindinglist,完全被看似简单的事情难住了,而且已经被杀了。。。但仍然难住了 我想做的是:我有一个WinForms列表框。它的项目被对象填充,DisplayMember被设置。当应用程序运行时,列出的项目中的数据可能会更改,包括DisplayMember后面的字段。发生这种情况时,我希望列表框中显示的文本发生变化,我还希望列表框自身重新排序,以便项目保持字母顺序 BindingList可以在数据更改时更新显示的文本,但就我而言,我无法对其进行排序 我回顾了这一点: 这里还有很多关于如何实现这一点的线程,但这些线

完全被看似简单的事情难住了,而且已经被杀了。。。但仍然难住了

我想做的是:我有一个WinForms列表框。它的项目被对象填充,DisplayMember被设置。当应用程序运行时,列出的项目中的数据可能会更改,包括DisplayMember后面的字段。发生这种情况时,我希望列表框中显示的文本发生变化,我还希望列表框自身重新排序,以便项目保持字母顺序

BindingList可以在数据更改时更新显示的文本,但就我而言,我无法对其进行排序

我回顾了这一点:

这里还有很多关于如何实现这一点的线程,但这些线程似乎都不适用于列表框

在列表框上设置Sorted属性同样没有帮助

我需要做什么才能让列表框自行排序

 private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
      //Sorting function
    }

那么这个呢???

您可以使用BindingSource对象。 只需将其拖放到表单中,并将ListBox.DataSource属性指向此BindingSource对象。 然后转到BindingSource的属性并根据需要定义排序

然后在代码中,您可以设置
myBindingSource.DataSource=myCollection
,瞧,您的列表框被填充和排序。
简单。

与Patrol02的帖子一样,您可能希望尝试将数据源设置为null,然后根据列表大小更改触发的事件重新分配数据源。您可以在集合上使用观察者模式,覆盖Add和Remove方法以通知观察者重新绑定自己。

重置数据源将有效地对列表框进行排序:

    listBox1.DataSource = null;
    listBox1.DataSource = myBindingList;
    listBox1.DisplayMember = "MyField";
但这不是自动的。据我所知,每当DisplayMember后面的字段通过事件或类似事件更新时,都应该进行排序

请查看我的完整测试:

public partial class Form1 : Form
{
    public BindingList<ABC> myBindingList = new BindingList<ABC>();

    public Form1() {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) {
        myBindingList.Add(new ABC("zzz"));
        myBindingList.Add(new ABC("aaa"));
    }

    private void button2_Click(object sender, EventArgs e) {
        myBindingList[0].MyField = "ccc"; // was "zzz"
        myBindingList[1].MyField = "ddd"; // was "aaa"

        listBox1.DataSource = null;
        listBox1.DataSource = myBindingList;
        listBox1.DisplayMember = "MyField";
    }

    private void Form1_Load(object sender, EventArgs e) {
        listBox1.DataSource = myBindingList;
        listBox1.DisplayMember = "MyField";

    }
}

public class ABC  {
    public string MyField { get; set; } 
    public ABC(string val) {
        MyField = val;
    }
}
公共部分类表单1:表单
{
public BindingList myBindingList=新建BindingList();
公共表格1(){
初始化组件();
}
私有无效按钮1\u单击(对象发送者,事件参数e){
添加(新ABC(“zzz”);
添加(新ABC(“aaa”);
}
私有无效按钮2\u单击(对象发送者,事件参数e){
myBindingList[0]。MyField=“ccc”;//是“zzz”
myBindingList[1]。MyField=“ddd”;//是“aaa”
listBox1.DataSource=null;
listBox1.DataSource=myBindingList;
listBox1.DisplayMember=“MyField”;
}
私有void Form1\u加载(对象发送方、事件参数e){
listBox1.DataSource=myBindingList;
listBox1.DisplayMember=“MyField”;
}
}
公共课ABC{
公共字符串MyField{get;set;}
公共ABC(字符串val){
MyField=val;
}
}

列表控件上的LVS\u排序样式应该可以工作,但您说不行。我会再次检查它是否适用。我从来没有遇到过自排序下拉列表控件的问题。请注意,这是我们所说的列表控件,而不是listview控件。

我通过创建一个新类BindingSortingList来实现这一点,该类继承自BindingList。在其中,我覆盖了所有必要的方法,如ApplySortCore()和RemoveSortCore()。当您应用排序时,在内部您基本上必须将其复制到具有排序功能的标准列表中,对其进行排序,然后将其复制回“this”列表中。这看起来很疯狂,但现在我有了一个可重用的类用于此目的。


<ListBox x:Name="UsersList"  SelectionChanged="SelectionChngd">
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Border BorderBrush="Red" BorderThickness="5">
                    <Grid MouseEnter="Grid_MouseEnter"> 
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                            <TextBlock   Text="{Binding Name}"/>
                        <TextBlock Grid.Row="1" Text="{Binding Email}"/>
                    </Grid>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>

        </ListBox>
名称空间SilverlightApplication8
{
公共部分类主页面:UserControl
{
ObservableCollection用户=新的ObservableCollection();
公共主页()
{
Service1Client客户端=新的Service1Client();
client.GetUsersCompleted+=已完成;
client.GetUsersAsync(5);
初始化组件();
image.Source=新的位图图像(新的Uri(@“c:\1.JPG”);
}    
私有无效已完成(对象发送方,GetUsersCompletedEventArgs e)
{
用户=e.Result;
UsersList.ItemsSource=用户;
}
私有void SelectionChngd(对象发送方,selectionchangedventargs e)
{
UserData u=(UserData)(UsersList.SelectedItem);
DescText.Text=u.Desc;
image.Source=新的位图图像(新的Uri(@)http://profile.ak.fbcdn.net/hprofile-ak-snc4/49939_713180125_9000_q.jpg"));
}
专用void Grid_MouseEnter(对象发送器,MouseEventArgs e)
{
if(UsersList.SelectedItem!=null)
{
UserData u=(UserData)(UsersList.SelectedItem);
DescText.Text=u.Desc;
}
}
}
}

您是直接绑定到BindingList,还是先使用数据源再使用BindingList?对于后者,我从来没有遇到过问题。我有一个对象列表(实际上是实体框架对象),我将这些对象传递给BindingList的构造函数,然后将该BindingList分配给ListBox的数据源。这将更新DisplayMember,但不会自动排序。由于BindingList不进行本机排序,所以这并不奇怪。但我似乎无法对它进行排序,即使我自己制作了它的派生版本,如MSDN示例中所示,也不是通过其他方法。我们这里讨论的是.Net的哪个版本?您是否考虑过自己实现IBindingList?我想知道您是否需要在BindingList中的项上使用INotifyPropertyChanged,以便ListBox在DisplayMember属性更改后知道如何使用?虽然如果ListBox不能正确处理,我不会感到惊讶……ListBox后面的数据实际上会随着所选站点的时间而改变
namespace SilverlightApplication8
{
    public partial class MainPage : UserControl
    {
        ObservableCollection<UserData> users = new ObservableCollection<UserData>();
        public MainPage()
        {
            Service1Client client = new Service1Client();
            client.GetUsersCompleted += completed;
            client.GetUsersAsync(5);
            InitializeComponent();

            image.Source = new BitmapImage(new Uri(@"c:\1.JPG"));
        }    

        private void completed(object sender, GetUsersCompletedEventArgs e)
        {
            users=e.Result;

            UsersList.ItemsSource = users;
        }

        private void SelectionChngd(object sender, SelectionChangedEventArgs e)
        {
            UserData u= (UserData)(UsersList.SelectedItem);
            DescText.Text = u.Desc;

            image.Source = new BitmapImage(new Uri(@"http://profile.ak.fbcdn.net/hprofile-ak-snc4/49939_713180125_9000_q.jpg"));
        }

        private void Grid_MouseEnter(object sender, MouseEventArgs e)
        {
            if (UsersList.SelectedItem != null)
            {
                UserData u = (UserData)(UsersList.SelectedItem);
                DescText.Text = u.Desc;
            }
        }
    }
}