2010-09-20 17 views
9

Totalmente perplejo por algo que parece fácil, y que se ha hecho a la muerte ... Sin embargo, todavía perplejo.Self Sorting Listbox

Lo que quiero hacer: Tengo un ListBox de WinForms. Sus elementos están llenos de objetos, se establece DisplayMember. A medida que se ejecuta la aplicación, los datos en los elementos enumerados pueden cambiar, incluido el campo detrás de DisplayMember. Quiero que el texto que se muestra en el ListBox cambie cuando esto ocurra, y también quiero que el ListBox vuelva a ordenarlo para que los elementos permanezcan en orden alfabético.

Un BindingList funciona bien para actualizar el texto que se muestra cuando los datos cambian, pero durante toda la vida, no logro ordenarlo.

he revisado este: http://msdn.microsoft.com/en-us/library/ms993236.aspx

además de numerosos hilos aquí acerca de cómo hacer esto, pero nada de esto parece que funciona para un cuadro de lista.

Establecer la propiedad ordenada en el ListBox es igualmente inútil.

¿Qué debo hacer para que un ListBox se ordene solo?

+0

¿Está uniéndose directamente a la BindingList o utilizando una fuente de datos a continuación BindingList? Nunca he tenido problemas con este último. – leppie

+0

Tengo una lista de objetos (en realidad objetos de Entity Framework), los paso al constructor de una BindingList y luego los asigno a DataSource de ListBox. Esto actualizará DisplayMember, pero no ordenará automáticamente. Como BindingList no se ordena de forma nativa, no es una sorpresa. Pero parece que no puedo ordenarlo, incluso cuando hago mi propia versión derivada, como en el ejemplo de MSDN, ni a través de otros enfoques. – Jack

+0

¿De qué versión de .Net estamos hablando aquí? –

Respuesta

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

¿Qué le parece esto?

+0

Los datos detrás de ListBox realmente cambiarán independientemente de cuando el elemento seleccionado cambie. El usuario seleccionará el artículo, que completará un formulario con la información del artículo, permitiéndole cambiarlo. Al hacerlo, pueden cambiar la propiedad detrás de DisplayMember en el Listbox. Es entonces cuando me gustaría volver a ordenar, que en realidad sería cuando presionen Guardar en la otra forma. Me trataron el cableado hasta el evento ListChanged del BindingList detrás del cuadro de lista, ordenados allí, vio el tipo BindingList, pero el cuadro de lista no dibujarse, sólo había actualizar el elemento cambiado. – Jack

1

Puede usar un objeto BindingSource. Simplemente arrastre y suelte en su formulario y apunte su propiedad ListBox.DataSource a este objeto BindingSource. Luego vaya a las propiedades de BindingSource y defina Ordenar como lo necesite.

Luego, en el código puede configurar myBindingSource.DataSource = myCollection y listo, su listbox está poblado y ordenado. Fácil.

+0

El BindingSource no parece volver a ordenar después de un cambio. Termina comportándose como lo hizo BindingList. Muestra el cambio de nombre de DisplayMember, pero no ordena los elementos. Traté de poner una SortableBindingList como su DataSource, que se mostró como SupportsSorting, pero cuando las cosas cambian, todavía no se ordena. – Jack

1

Al igual que con la publicación de Patrol02, sin embargo, es posible que desee intentar configurar el DataSource como nulo y luego reasignarlo en función de un evento desencadenado por el cambio de tamaño de la lista. Podría usar el patrón de observador en la colección, anulando los métodos Agregar y Eliminar para notificar a los observadores que se vuelvan a unir.

+0

Una opción que sí funciona es utilizar una lista de vinculación, que tiene un evento para ListChanged, conectarse a ese evento, detectar un cambio y usarlo como una señal para volver a llenar el ListBox. Descubrí que el enlace al DataSource no funcionaba bien aquí, y en su lugar uno tiene que Borrar y volver a llenar los elementos en el ListBox. Esto es un poco poco elegante, espero que haya una mejor solución ... Pero funciona. – Jack

1

Restablecimiento de la fuente de datos va a clasificar de manera efectiva el ListBox:

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

Pero eso no es automático. Según tengo entendido, la clasificación debería ocurrir cada vez que se actualiza el campo detrás de la DisplayMember, a través de un evento o algo por el estilo ...

Véase mi ensayo completo de todas formas:

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

El estilo LVS_SORT en el control de la lista debería funcionar, pero dices que no. Verificaría que esté aplicado. Nunca he tenido ningún problema con un control de lista desplegable de auto clasificación. Tenga en cuenta que estamos hablando de un control de lista, no de un control de vista de lista.

1

Lo hice creando una nueva clase, BindingSortingList, que heredó de BindingList. En él anulé todos los métodos necesarios, como ApplySortCore() y RemoveSortCore(). Cuando aplica el ordenamiento, internamente básicamente tiene que copiarlo en una lista estándar, que tiene capacidad de clasificación, ordenarlo y luego copiarlo nuevamente en la lista "this". Parece una locura, pero ahora tengo una clase reutilizable para este propósito.

-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 porque este código no tiene nada que ver con la pregunta. Si me equivoco, edite su respuesta y hágala más clara. –