2010-09-20 10 views
9

Całkowicie zakłopotany przez coś, co wydaje się łatwe, i zostało zrobione na śmierć ... A jednak nadal jest zakłopotany.Self Sorting Listbox

Co chcę zrobić: Mam ListBox WinForm. Jej elementy są wypełnione obiektami, ustawiony jest DisplayMember. W trakcie działania aplikacji dane w wymienionych pozycjach mogą ulec zmianie, w tym pola za DisplayMember. Chcę, aby tekst wyświetlany w polu ListBox zmieniał się, gdy tak się stanie, a także chcę, aby ListBox ponownie się sortował, aby elementy pozostały w kolejności alfabetycznej.

A BindingList działa dobrze, aby zaktualizować wyświetlany tekst, gdy dane się zmieniają, ale na moje życie, nie mogę go posortować.

Sprawdziliśmy to: http://msdn.microsoft.com/en-us/library/ms993236.aspx

Plus liczne tutaj o tym, jak to zrobić wątków, ale żaden z nich wydaje się działać dla ListBox.

Ustawienie sortowanej właściwości na liście list jest również niepomocne.

Co muszę zrobić, aby listbox sam się sortował?

+0

Czy wiążące bezpośrednio do BindingList lub używając DataSource następnie BindingList? Nigdy nie miałem problemów z tym ostatnim. – leppie

+0

Mam listę obiektów (w rzeczywistości obiektów Entity Framework), przekazuję je do konstruktora BindingList, a następnie przypisanie tej BindingList do DataSource ListBox. Spowoduje to aktualizację DisplayMember, ale nie będzie sortować automatycznie. Ponieważ BindingList nie sortuje natywnie, to nie jest niespodzianka. Ale nie mogę tego zmusić do sortowania, nawet gdy tworzę własną pochodną wersję tego, jak w przykładzie MSDN, ani za pomocą innych podejść. – Jack

+0

O jakiej wersji .Net mówimy tutaj? –

Odpowiedz

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

Co z tym zrobić?

+0

Dane za ListBox będą się zmieniać niezależnie od tego, kiedy zmieni się wybrany element. Użytkownik wybierze element, który wypełni formularz informacjami o przedmiocie, umożliwiając ich zmianę. W ten sposób mogą zmienić właściwość za DisplayMember na Listbox. Właśnie wtedy chciałbym, żeby to było ponownie sortowane, co w rzeczywistości nastąpi, gdy uderzą Save w innej formie. Próbowałem okablowania do zdarzenia ListChanged z BindingList za ListBox, posortowane tam, zobaczył sortowanie BindingList, ale ListBox nie przerysował się, to by tylko zaktualizować zmieniony element. – Jack

1

Możesz użyć obiektu BindingSource. Po prostu przeciągnij i upuść go do formularza i wskaż właściwość ListBox.DataSource na ten obiekt BindingSource. Następnie przejdź do właściwości BindingSource i definiuj Sortuj według potrzeb.

Następnie w kodzie można ustawić myBindingSource.DataSource = myCollection i voila, twój listbox jest wypełniony i posortowany. Łatwo.

+0

Źródło BindingSource nie wydaje się ponownie sortować po zmianie. Kończy się to w sposób podobny do BindingList. Pokazuje zmianę nazwy DisplayMember, ale nie sortuje elementów. Próbowałem umieścić SortableBindingList jako jego DataSource, pokazał jako SupportsSorting, ale kiedy rzeczy się zmieniają, nadal nie sortuje. – Jack

1

Podobnie jak w przypadku postu Patrol02, jednak warto spróbować ustawić źródło danych na wartość null, a następnie ponownie przypisać je na podstawie zdarzenia wywołanego zmianą rozmiaru listy. Można użyć wzorca obserwatora w kolekcji, przesłaniając metody Dodaj i usuń, aby powiadomić obserwatorów, aby się ponownie powiązali.

+0

Jedną z opcji, która działa, jest użycie listy BindingList, która ma zdarzenie dla ListChanged, podłączenie do tego zdarzenia, wykrycie zmiany i użycie go jako wskazówki do ponownego wypełnienia listy. Okazało się, że powiązanie z DataSource nie działa tutaj dobrze, a zamiast tego należy wyczyścić i ponownie zaludnić elementy w ListBox. To jest trochę nieeleganckie, mam nadzieję, że jest lepsze rozwiązanie ... Ale to działa. – Jack

1

Resetowanie DataSource skutecznie sortować ListBox:

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

Ale to nie jest automatyczne. Jak rozumiem, sortowanie powinno się zdarzyć, gdy pole za DisplayMember jest aktualizowany, przez zdarzenia lub coś takiego ...

Zobacz mój pełny test i tak:

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

Styl LVS_SORT sprawie kontroli listy powinno działać, ale mówisz, że tak nie jest. Dokładnie sprawdziłbym, czy jest zastosowany. Nigdy nie miałem problemów z samoczynnym sortowaniem listy rozwijanej. Zauważ, że jest to kontrolka listy, o której mówimy, a nie kontrolka listview.

1

Zrobiłem to, tworząc nową klasę, BindingSortingList, która odziedziczyła po BindingList. W nim przejąłem wszystkie niezbędne metody, takie jak ApplySortCore() i RemoveSortCore(). Kiedy zastosujesz sortowanie, wewnętrznie musisz skopiować go do standardowej listy, która ma zdolność sortowania, posortuj ją, a następnie skopiuj z powrotem do "tej" listy. Wydaje się to szalone, ale teraz mam do tego celu klasę wielokrotnego użytku.

-2
<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> 
-4
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; 
      } 
     } 
    } 
} 
+1

-1 ponieważ ten kod nie ma nic wspólnego z pytaniem. Jeśli się mylę, edytuj swoją odpowiedź i wyraź ją. –