2011-10-07 103 views
7

我花了很多时间处理这个问题。将可观察的集合绑定到XAML中的ListBox

我有一个数据类:

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

} 

接下来我有一类UserClass的类的ObservableCollection:

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

事实上,经过大量的测试编辑,代码很大一部分的不起作用,比如序列化。但是,数据绑定和绑定不是必须的,现在我正在解决这个问题。

所以我有这个集合,并希望将它绑定到listBox。 我尝试了几种方法,但没有得到它的工作。

最后一个我想给我的写错误:

The resource 'users' cannot be resolved.

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

作为第一炮,我会尽量让类和它的公共 – thumbmunkeys

+6

性质就我个人而言,我求你不要用“类后缀所有的类名 –

回答

26

几点要注意的

  • 使属性public而不是private
  • make变量private
  • 遵循命名约定,不要在课后添加class
  • ItemsSource你提供的数据应该按照数据的范围,在我的例子中,类范围中的用户列表和我已经提供了窗口加载事件的ItemSource。

这里是一个完整的示例代码,在这里我已经在ListBox中嵌套了网格控件,因为稍后您可以更改VirtualizationStackPanel的ListBox属性。 因此,当您在列表中进行大量更新时,它会带来巨大的性能提升。 也可以使用BindingList,这在我看来比ObservableCollection更好。

用户等级:

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

用户列表类:

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> 

XAML代码背后:

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

非常感谢。 “UserList.ItemsSource = userslist;” XAML代码确实帮了我很大忙。 – prespic

+1

我知道这是很久以前的事了,但是这对我非常有帮助。这样一个简洁的答案。当ListBox本身加载时,我正在收到一个错误,但是我已经在代码的帮助下解决了很多错误。奖励! – plast1K

2

你需要做两件事情:

首先设置任何元素(Window/UserControl /的DataContext什么)包含您的ListBox以看起来像这样的对象:

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

这是您的视图模型,它是您想要绑定到的内容。

其次,将您的绑定更改为ItemsSource="{Binding Path=users}"。这转化为“为我设置ItemsSource财产的财产usersthis.DataContext价值的价值。因为DataContext是继承自父,你将此项设定到ViewModel级以上,你ListBox现在将显示您的用户列表。

相关问题