结合观察集合到列表框在XAML [英] Binding observable collection to ListBox in XAML

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

问题描述

我花了大量的时间解决这个问题。

我有数据的类:

 类UserClass的:INotifyPropertyChanged的
{
    公众诠释_key;
    私人字符串_fullName;
    私人字符串_nick;    公众诠释的关键
    {
        {返回_key;}
        集合{_key =价值; NotifyPropertyChanged(钥匙); }
    }
    私人字符串缺口
    {
        {返回_nick; }
        集合{_nick =价值; NotifyPropertyChanged(缺口); }
    }
    私人字符串全名
    {
        {返回_fullName; }
        集合{_fullName =价值; NotifyPropertyChanged(全名); }
    }
    公共UserClass的()
    {
        尼克=昵称;
        全名=全名;
    }    公共UserClass的(字符串昵称,字符串名称,诠释键)
    {
        this.nick =缺口;
        this.fullName =名称;
    }
    // INotifzPropertyChanged实施
    公共事件PropertyChangedEventHandler的PropertyChanged;
    私人无效NotifyPropertyChanged(字符串propertyName的)
    {
        如果(的PropertyChanged!= NULL)
        {
            的PropertyChanged(这一点,新PropertyChangedEventArgs(propertyName的));
        }
    }    公共重写字符串的ToString()
    {
        返回的String.Format({0} {1},{2}键,千钧一发之际,全名);
    }}

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

 类userListClass:与的ObservableCollection LT; UserClass的>
{
    公共userListClass(){}    //公共覆盖无效添加(UserClass的用户)
    // {
    // //user.PropertyChanged + =新PropertyChangedEventHandler(用户);
    // base.Add(用户);
    //}    〜userListClass()
    {
        //连载();
    }    公共无效序列化(的ObservableCollection<&UserClass的GT; usersColl)
    {
        的FileStream FS =新的FileStream(DataFile.dat,FileMode.Create);
        BinaryFormatter的格式化=新的BinaryFormatter();
        尝试
        {
            formatter.Serialize(FS,usersColl);
        }
        赶上(SerializationException E)
        {
            Console.WriteLine(无法序列原因:+ e.Message);
            扔;
        }
        最后
        {
            fs.Close();
        }
    }    公共无效反序列化()
    {
        的FileStream FS =新的FileStream(DataFile.dat,FileMode.Open);
        尝试
        {
            BinaryFormatter的格式化=新的BinaryFormatter();
            //用户=(哈希表)formatter.Deserialize(FS);
            // usersColl =(的ObservableCollection<&UserClass的GT;)formatter.Deserialize(FS);
        }
        赶上(SerializationException E)
        {
            的MessageBox.show(错误:+ e.Message);
            扔;
        }
        最后
        {
            fs.Close();
        }
    }
    公共重写字符串的ToString()
    {
        返回测试;
    //返回base.ToString();
    }
}

在事实上,很多测试编辑之后,code的很大一部分不能正常工作,如序列化。但它是没有必要的数据绑定和绑定是什么,我现在解决。

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

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


  

资源用户不能得到解决。


 <列表框Grid.Column =0NA​​ME =userViewLeft的ItemsSource ={绑定源= {StaticResource的用户}}/>


解决方案

要注意几点


  • 请属性公共,而不是私人

  • 请变量私人

  • 按照命名规则,不追加类的后面。

  • 的ItemsSource 你的供应应根据数据的范围,在我的例子中类范围的用户列表和我所提供的的ItemSource上的窗口已加载的事件。

下面是一个完整的例子code,在此我有嵌套网格控件列表框里面,因为以后你可以更改列表框属性VirtualizingStackPanel。
当你有名单上的大量更新,以便它会给巨大的性能增益。
你也可以使用的BindingList 这在我看来是比的ObservableCollection 更好的性能明智的。

用户等级:

 公共类用户:INotifyPropertyChanged的
    {
        私人诠释_key;
        私人字符串_fullName;
        私人字符串_nick;        公众诠释的关键
        {
            {返回_key; }
            集合{_key =价值; NotifyPropertyChanged(钥匙); }
        }
        公共字符串昵称
        {
            {返回_nick; }
            集合{_nick =价值; NotifyPropertyChanged(昵称); }
        }
        公共字符串名称
        {
            {返回_fullName; }
            集合{_fullName =价值; NotifyPropertyChanged(姓名); }
        }        公共用户(字符串昵称,字符串名称,诠释键)
        {
            this.NickName =缺口;
            this.Name =名称;
            this.Key =键;
        }        公共事件PropertyChangedEventHandler的PropertyChanged;
        私人无效NotifyPropertyChanged(字符串propertyName的)
        {
            如果(的PropertyChanged!= NULL)
            {
                的PropertyChanged(这一点,新PropertyChangedEventArgs(propertyName的));
            }
        }        公共重写字符串的ToString()
        {
            返回的String.Format({0} {1},{2},重点,昵称,姓名);
        }
    }

用户列表类:

 公共类用户:的ObservableCollection<使用者>
    {
        公众用户()
        {
            加入(新用户(Jamy,詹姆斯·史密斯,计数));
            加入(新用户(Mairy,玛丽·海耶斯,计数));
            加入(新用户(乳业,卡里遗嘱,计数));
        }
    }

XAML:

 <网格和GT;
        <按钮内容=开始高度=23的Horizo​​ntalAlignment =左保证金=416,12,0,0X:NAME =Button1的VerticalAlignment =评出的WIDTH =75点击=的button1_Click />
        < ListBox的X:名称=UserList的Horizo​​ntalContentAlignment =拉伸保证金=12,41,12,12>
            < ListBox.ItemTemplate>
                <&DataTemplate的GT;
                        <电网保证金=10>
                            < Grid.ColumnDefinitions>
                                < ColumnDefinition宽度=20/>
                                < ColumnDefinition WIDTH =150/>
                                &所述; ColumnDefinition宽度=*/>
                            < /Grid.ColumnDefinitions>
                            < TextBlock的文本={结合重点}保证金=3Grid.Column =0/>
                            < TextBlock的文本={结合昵称}保证金=3Grid.Column =1/>
                            < TextBlock的文本={绑定名称}保证金=3Grid.Column =2/>
                        < /网格和GT;
                < / DataTemplate中>
            < /ListBox.ItemTemplate>
        < /列表框>
    < /网格和GT;

后面的 XAML code:

 公共部分类主窗口:窗口
{
    公共静态用户userslist =新用户();
    DispatcherTimer定时器=新DispatcherTimer();    公共主窗口()
    {
        的InitializeComponent();
        this.Loaded + =新RoutedEventHandler(MainWindow_Loaded);
    }    无效MainWindow_Loaded(对象发件人,RoutedEventArgs E)
    {
        timer.Interval = DateTime.Now.AddSeconds(10) - DateTime.Now;
        timer.Tick + =新的EventHandler(timer_Tick);
        UserList.ItemsSource = userslist;
    }    无效timer_Tick(对象发件人,EventArgs的发送)
    {
        userslist.Add(新用户(Jamy - + userslist.Count,詹姆斯·史密斯,userslist.Count));
        userslist.Add(新用户(Mairy - + userslist.Count,玛丽·海斯,userslist.Count));
        userslist.Add(新用户(乳业 - + userslist.Count,卡里遗嘱,userslist.Count));
    }    私人无效的button1_Click(对象发件人,RoutedEventArgs E)
    {
        如果(button1.Content.ToString()==开始)
        {
            button1.Content =停止;
            timer.Start();
        }
        其他
        {
            button1.Content =开始;
            timer.Stop();
        }
    }}

I've spent lots of hours with this problem.

I have a class with data:

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

}

Next I have a class with observablecollection of userClass class:

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

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:

The resource 'users' cannot be resolved.

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

解决方案

Some points to be noted

  • 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.

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.

User class:

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

User List class:

    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 Code behind:

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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