2011-10-07 22 views
7

He pasado muchas horas con este problema.Vinculación colección observable a ListBox en XAML

tengo una clase con los datos:

class userClass : INotifyPropertyChanged 
{ 
    public int _key; 
    private string _fullName; 
    private string _nick; 

    public int key 
    { 
     get{return _key;} 
     set { _key = value; NotifyPropertyChanged("key"); } 
    } 
    private string nick 
    { 
     get { return _nick; } 
     set { _nick = value; NotifyPropertyChanged("nick"); } 
    } 
    private string fullName 
    { 
     get { return _fullName; } 
     set { _fullName = value; NotifyPropertyChanged("fullName"); } 
    } 


    public userClass() 
    { 
     nick = "nickname"; 
     fullName = "fullname"; 
    } 

    public userClass(String nick, String name, int key) 
    { 
     this.nick = nick; 
     this.fullName = name; 
    } 


    //INotifzPropertyChanged implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public override string ToString() 
    { 
     return string.Format("{0} {1}, {2}", key, nick, fullName); 
    } 

} 

siguiente que tiene una clase con ObservableCollection de clase userClass:

class userListClass : ObservableCollection<userClass> 
{ 
    public userListClass(){} 

    //public override void Add(userClass user) 
    //{ 
    // //user.PropertyChanged += new PropertyChangedEventHandler(user); 
    // base.Add(user); 
    //} 

    ~userListClass() 
    { 
     //Serialize(); 
    } 

    public void Serialize(ObservableCollection<userClass> usersColl) 
    { 
     FileStream fs = new FileStream("DataFile.dat", FileMode.Create); 
     BinaryFormatter formatter = new BinaryFormatter(); 
     try 
     { 
      formatter.Serialize(fs, usersColl); 
     } 
     catch (SerializationException e) 
     { 
      Console.WriteLine("Failed to serialize. Reason: " + e.Message); 
      throw; 
     } 
     finally 
     { 
      fs.Close(); 
     } 
    } 

    public void Deserialize() 
    { 
     FileStream fs = new FileStream("DataFile.dat", FileMode.Open); 
     try 
     { 
      BinaryFormatter formatter = new BinaryFormatter(); 
      //users = (Hashtable) formatter.Deserialize(fs); 
      //usersColl = (ObservableCollection<userClass>)formatter.Deserialize(fs); 
     } 
     catch (SerializationException e) 
     { 
      MessageBox.Show(" Error: " + e.Message); 
      throw; 
     } 
     finally 
     { 
      fs.Close(); 
     } 
    } 




    public override string ToString() 
    { 
     return "test"; 
    //return base.ToString(); 
    }  
} 

De hecho, después de mucho probar una edición, gran parte del código no funciona, como la serialización. Pero no es necesario para el enlace de datos y vinculante es lo que estoy resolviendo ahora.

Tengo esta colección y quiero vincularla a listBox. He intentado de varias maneras, pero no lo he hecho funcionar.

La última vez que lo intenté me dio el error de escritura:

The resource 'users' cannot be resolved.

<ListBox Grid.Column="0" Name="userViewLeft" ItemsSource="{Binding Source={StaticResource users} }" /> 
+3

como un primer disparo, que iba a tratar de hacer la clase y sus propiedades públicas – thumbmunkeys

+6

En una nota personal, yo pido que no sufijo todos sus nombres de las clases con 'clase' –

Respuesta

26

Algunos puntos a tener en cuenta

  • Convertir las propiedades public y no private.
  • Hacer variables private.
  • Siga las Convenciones de denominación y no añada class detrás de la clase.
  • ItemsSource que el suministro debe ser según el alcance de los datos, en mi ejemplo, la lista de usuarios en el alcance de la clase y he proporcionado el ItemSource en evento de Windows cargado.

Aquí está el código de un ejemplo completo, En esto he anidado dentro de la cuadrícula del control de cuadro de lista porque más adelante se puede cambiar la propiedad ListBox para VirtualizingStackPanel. Para que brinde una gran ganancia de rendimiento cuando tiene grandes actualizaciones en la lista. También puede usar BindingList que en mi opinión es mejor que ObservableCollection en cuanto a rendimiento.

clase Usuario: clase List

public class User : INotifyPropertyChanged 
    { 
     private int _key; 
     private string _fullName; 
     private string _nick; 

     public int Key 
     { 
      get { return _key; } 
      set { _key = value; NotifyPropertyChanged("Key"); } 
     } 
     public string NickName 
     { 
      get { return _nick; } 
      set { _nick = value; NotifyPropertyChanged("NickName"); } 
     } 
     public string Name 
     { 
      get { return _fullName; } 
      set { _fullName = value; NotifyPropertyChanged("Name"); } 
     } 

     public User(String nick, String name, int key) 
     { 
      this.NickName = nick; 
      this.Name = name; 
      this.Key = key; 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void NotifyPropertyChanged(String propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public override string ToString() 
     { 
      return string.Format("{0} {1}, {2}", Key, NickName, Name); 
     } 
    } 

usuario:

public class Users : ObservableCollection<User> 
    { 
     public Users() 
     { 
      Add(new User("Jamy", "James Smith", Count)); 
      Add(new User("Mairy", "Mary Hayes", Count)); 
      Add(new User("Dairy", "Dary Wills", Count)); 
     } 
    } 

XAML:

<Grid> 
     <Button Content="Start" Height="23" HorizontalAlignment="Left" Margin="416,12,0,0" x:Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> 
     <ListBox x:Name="UserList" HorizontalContentAlignment="Stretch" Margin="12,41,12,12"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
         <Grid Margin="10"> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="20" /> 
           <ColumnDefinition Width="150" /> 
           <ColumnDefinition Width="*" /> 
          </Grid.ColumnDefinitions> 
          <TextBlock Text="{Binding Key}" Margin="3" Grid.Column="0" /> 
          <TextBlock Text="{Binding NickName}" Margin="3" Grid.Column="1" /> 
          <TextBlock Text="{Binding Name}" Margin="3" Grid.Column="2" /> 
         </Grid> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 

Código XAML atrás:

public partial class MainWindow : Window 
{ 
    public static Users userslist = new Users(); 
    DispatcherTimer timer = new DispatcherTimer(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Loaded += new RoutedEventHandler(MainWindow_Loaded); 
    } 

    void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     timer.Interval = DateTime.Now.AddSeconds(10) - DateTime.Now; 
     timer.Tick += new EventHandler(timer_Tick); 
     UserList.ItemsSource = userslist; 
    } 

    void timer_Tick(object sender, EventArgs e) 
    { 
     userslist.Add(new User("Jamy - " + userslist.Count, "James Smith", userslist.Count)); 
     userslist.Add(new User("Mairy - " + userslist.Count, "Mary Hayes", userslist.Count)); 
     userslist.Add(new User("Dairy - " + userslist.Count, "Dary Wills", userslist.Count)); 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     if (button1.Content.ToString() == "Start") 
     { 
      button1.Content = "Stop"; 
      timer.Start(); 
     } 
     else 
     { 
      button1.Content = "Start"; 
      timer.Stop(); 
     } 
    } 

} 
+2

muchas gracias. "UserList.ItemsSource = userslist;" y el código XAML me ayudó mucho. – prespic

+1

Sé que esto fue hace mucho tiempo, pero esto me ha ayudado inmensamente. Una respuesta tan concisa. Actualmente recibo un error cuando se carga el 'ListBox', en referencia al enlace, pero he trabajado tantos errores con la ayuda de su código. ¡Prestigio! – plast1K

2

Que tiene que hacer 2 cosas:

En primer lugar, establezca la DataContext de cualquier elemento (Window/UserControl/lo que sea) contiene su ListBox a un objeto que se parece a:

public class ViewModel 
{ 
    public ViewModel() { this.users = new userListClass(); } 
    public userListClass users { get; private set; } 
} 

Este es su modelo de vista, y es a lo que quiere vincularse.

En segundo lugar, cambie su encuadernación a ItemsSource="{Binding Path=users}". Esto se traduce en "establecer el valor de mi ItemsSource propiedad en el valor de la propiedad users en this.DataContext. Debido a que el DataContext se hereda de los padres, y lo ajusta a la clase ViewModel anteriormente, su ListBox ahora mostrará la lista de usuarios.

Cuestiones relacionadas