开发者

Self Sorting Listbox

Totally stumped by something that seems easy, and has been done to death... Yet still stumped.

What I want to do: I've got a WinForms ListBox. Its items are populated with objects, the DisplayMember is set. As the app runs, the data in the listed items might change, including the field behind the DisplayMember. I want the text displayed in the ListBox to change when this happens, and I also want the ListBox to re-sort itself so the items remain in alphabetical order.

A BindingList works fine to update the displayed text when the data changes, but for the life of me, I can't get it to sort.

I reviewed this: http://msdn.microsoft.com/en-us/library/ms993236.aspx

Plus 开发者_开发百科numerous threads here about how to do this, but none of it seems to work for a ListBox.

Setting the Sorted property on the ListBox is similarly unhelpful.

What do I need to do to get a ListBox to sort itself?


You can use a BindingSource object. Just drag-n-drop it into your form and point your ListBox.DataSource property to this BindingSource object. Then go to the BindingSource's properties and define Sort as you need.

Then in code you can set myBindingSource.DataSource = myCollection and voila, your listbox is populated and sorted. Easy.


As with Patrol02's post, however you may want to try setting the DataSource to null and then reassigning it based on an event triggered by the list size changing. You could use the observer pattern on the collection, overriding the Add and Remove methods to notify watchers to rebind themselves.


Resetting the DataSource will effectively sort the ListBox:

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

But that's not automatic. As I understand, sorting should happen whenever the field behind the DisplayMember is updated, through an event or something like that...

See my complete test anyway:

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


The LVS_SORT style on the list control should work, but you say it doesn't. I would double check that it is applied. I've never had any trouble with a self-sorting drop-down list control. Note this is a list control we're speaking of, not a listview control.


I did this by creating a new class, BindingSortingList, which inherited from BindingList. In it I overrode all the necessary methods, like ApplySortCore() and RemoveSortCore(). When you apply the sort, internally you basically have to copy it to a standard list, which has sorting ability, sort it, then copy it back into the "this" list. It seems crazy but now I have a reusable class for this purpose.


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

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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜