将可观察集合绑定到 XAML 中的 ListBox [英] Binding observable collection to ListBox in XAML

查看:19
本文介绍了将可观察集合绑定到 XAML 中的 ListBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这个问题上花了很多时间.

I've spent lots of hours with this problem.

我有一个包含数据的类:

I have a class with data:

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 Nick
    {
        get { return _nick; }
        set { _nick = value; NotifyPropertyChanged("Nick"); }
    }
    public string FullName
    {
        get { return _fullName; }
        set { _fullName = value; NotifyPropertyChanged("FullName"); }
    }


    public User()
    {
        Nick = "nickname";
        FullName = "fullname";
    }

    public User(String nick, String name, int key)
    {
        Nick = nick;
        FullName  = name;
    }


    //INotifyPropertyChanged 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 的类:

Next I have a class with observablecollection of userClass class:

public class UserList : ObservableCollection<UserList>
{
    public UserList (){}

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

    public void Serialize(ObservableCollection<UserList> 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();
        }
    }

}

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

In fact, after lots of testing an editing, big part of code doesn't work, like serialization. But it is not necessary for data binding and binding is what i am solving now.

所以我有这个集合并想将它绑定到列表框.我尝试了几种方法,但还没有奏效.

So i have this collection and want to bind it to listBox. I tried several ways, but haven't got it to work.

我尝试的最后一个给了我写错误:

The last one I tried gave me the write error:

无法解析资源用户".

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

推荐答案

需要注意的几点

  • 将属性设为 public 而不是 private.
  • 将变量设为私有.
  • 遵循命名约定,不要在类后面附加 class.
  • ItemsSource 您应根据数据范围提供,在我的示例中,类范围内的用户列表和我在 Window Loaded 事件上提供了 ItemSource.
  • Make Properties public and not private.
  • Make Variables private.
  • Follow Naming Conventions and don't append class behind the class.
  • ItemsSource you supply should be as per scope of the data, In my example the userlist in class scope and I have provided the ItemSource on Window Loaded event.

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

Here is the an complete example code, In this I have nested the Grid Control inside ListBox because later on you can change the ListBox property for VirtualizingStackPanel. So that it would give huge performance gain when you have heavy updates on the list. Also you can use BindingList which is in my opinion better than ObservableCollection performance wise.

用户类别:

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

}

这篇关于将可观察集合绑定到 XAML 中的 ListBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆