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

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

问题描述

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

I've spent lots of hours with this problem.

我有一个数据类:

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.

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

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天全站免登陆