none
listbox绑定数据问题 RRS feed

  • 问题

  •  

    我用一个List<> 给listbox 绑定了数据,如后我选中其中的一行进行了操作,在操作完成后,把相应的List<> 中的数据 remove掉,然后再重新给 Listbox ItemsSource 赋值,但是,更新的绑定并没有任何作用,请问怎么解决这个问题
    2008年8月27日 8:53

答案

  • 你好,其实你的问题在于UI线程的问题,你操作数据源必须是UI线程发起才会有效,请看我的博客:

    http://hi.baidu.com/zhenyk/blog/item/bbf49051938c041e377abeef.html

    在所有.NET的窗体应用程序、Silverlight应用程序中,需要改变UI显示的操作,必须采用委托的方式显示进行异步操作,否则,UI线程不会响应,也就是你说的操作之后没有效果。

    如果还不会请留言,我再教你。

    原文:

    UI线程和Silverlight数据绑定的问题、错误和解决方案
    2008-09-01 04:03 P.M.

           最近的项目中利用了数据绑定来实现从服务器端来的数据的现实,在实际操作的过程中发现了一些问题,在这里总结一下,希望给Silverlight开发的朋友们带来一些帮助。
           在我的方案中,服务器会返回一些数据,返回的方法用前面文章中介绍的长连接服务器推送的方式来实现,服务器返回数据之后为了避免每次都发送数据到UI进行显示,采用了数据绑定的方式,在显示控件上绑定一个数据源实例,再把该数据源实例的引用发送给网络通信层协议解析部分,协议解析部分只要能正确的分析并将数据填充到数据源中即可,数据源的定义采用了前面这篇文章《自定义IList<T>完整实现》中介绍的IList<T>来实现。
           在开发过程中遇到的问题非常奇怪,将数据绑定后修改数据源不能自动更新在界面中,同时,跟踪调试的时候发现,数据源的非只读操作都会报错,先是数据类型不匹配的错误,采用委托方式进行非只读操作之后又报出线程操作有错误。在网上也无法查到有关资料和介绍,百思不得其解。最终,我认为应该是UI线程的问题。大家要牢记一件事,任何需要UI有响应(例如:改变图片路径导致UI重新加载图片、给TextBox.Text赋值等操作)有改变的操作,必须由UI发起,这种发起只有以下两种方式:
           1、同步方式:
                同步方式指利用某个UI事件的响应程序进行需要UI有响应有改变的操作,比如,我们可以在某个Button的Click事件的处理程序中进行操作,这里的操作有个要求“必须是同步的”,就是说事件处理程序的函数体执行操作之前必须把最终结果计算清楚,然后赋值。
               示例:
            private void stop_Click(object sender, RoutedEventArgs e)
            {           
                this.Sysinfo.text = "Stop_Clicked";
            }
            错误做法:
    private void stop_Click(object sender, RoutedEventArgs e)    
        { 
          (new Thread(new ThreadStart(() => { Dispatcher.BeginInvoke(UILoaded); }))).Start();
    }


    void UILoaded()
    {
    this.Sysinfo.text = "Stop_Clicked";
    }
    在上面的例子里我们能看到,必须要把赋值操作做完,否则,UI是不会响应,如果UI被迫自动响应,
    例如数据绑定的时候,我们还会收到系统报错和程序崩溃。

           2、异步方式:
                在异步方式中,我们之前讲过,如果修改UI的内容必须要发起一个委托,由UI线程进行具体的操作,例如:public delegate void addBudyGroupList(Kernel.Account.BuddyGroupList BGL, object BGObject);使用这样的方式声明一个委托,然后实现委托:
    private void AddBudyGroupListSub(Kernel.Account.BuddyGroupList BGL, object BG)
            {
                BGL.FolderList.Add((Kernel.Account.BuddyGroup)BG);
            }
    使用的方法:
    addBudyGroupList myWB;
    myWB = new addBudyGroupList(AddBudyGroupListSub);
    this.Dispatcher.BeginInvoke(myWB, new Object[] { myFL, (Kernel.Account.BuddyGroup)e.buddyFolderList });
    这里在实际操作数据源的时候采用委托的方式进行就不会报错了,我们可以放心的绑定一个数据源:
    public delegate void setDataSource(DataGrid target, Kernel.Account.BuddyGroupList BGL);
            private void setDataSourceSub(DataGrid target, Kernel.Account.BuddyGroupList BGL)
            {
                target.ItemsSource = BGL.FolderList;
            }

    setDataSource myW = new setDataSource(setDataSourceSub);
    this.Dispatcher.BeginInvoke(myW, new Object[] { this.MyDG, myFL });

    最后总结一下吧,所有涉及UI会发生改变,无论是类似DataBind的自动改变还是类似于“Textbox.text='asd';”之类的手动设置,我们都必须放在UI线程中进行,UI线程是独立于整个应用程序的一个基础线程,所有异步操作或多线程操作都不能直接向UI发送数据修改的请求,必须通过委托的方式发起。

    如果大家还有疑问可以回复,我会尽量及时回复:)

     

    2008年9月9日 3:23

全部回复

  • silverlight中的数据绑定有三种方式:OneWay,TwoWay和OneTime。如果你需要修改界面上的数据并同步更新后台的数据,请用TwoWay方式绑定。

     

    并且,请将集合的元素实现 INotifyPropertyChanged 来获得更新。或者使用 ObservableCollection<T> 集合类来绑定。

    2008年8月27日 9:18
    版主
  • 大哥,不是很明白啊 我就像给listbox 赋值变化下 怎么这么复杂,能给举个例子吗?

     

    2008年8月27日 9:39
  • 啊。这个。。。。

     

    Silverlight里的数据绑定就是这种原理。因为有时候我们需要修改界面上的数据,并且更新后台的数据,这个时候使用TwoWay方式绑定的话,可以让Silverlight帮我们完成许多功能。

     

    如果直接指定数据源的方式就是OneTime绑定,绑定一次之后,数据源和界面UI互不相干了。

     

    建议先看看数据绑定的知识吧:http://silverlight.net/learn/tutorials/databinding.aspx

    2008年8月27日 10:00
    版主
  • 你好,其实你的问题在于UI线程的问题,你操作数据源必须是UI线程发起才会有效,请看我的博客:

    http://hi.baidu.com/zhenyk/blog/item/bbf49051938c041e377abeef.html

    在所有.NET的窗体应用程序、Silverlight应用程序中,需要改变UI显示的操作,必须采用委托的方式显示进行异步操作,否则,UI线程不会响应,也就是你说的操作之后没有效果。

    如果还不会请留言,我再教你。

    原文:

    UI线程和Silverlight数据绑定的问题、错误和解决方案
    2008-09-01 04:03 P.M.

           最近的项目中利用了数据绑定来实现从服务器端来的数据的现实,在实际操作的过程中发现了一些问题,在这里总结一下,希望给Silverlight开发的朋友们带来一些帮助。
           在我的方案中,服务器会返回一些数据,返回的方法用前面文章中介绍的长连接服务器推送的方式来实现,服务器返回数据之后为了避免每次都发送数据到UI进行显示,采用了数据绑定的方式,在显示控件上绑定一个数据源实例,再把该数据源实例的引用发送给网络通信层协议解析部分,协议解析部分只要能正确的分析并将数据填充到数据源中即可,数据源的定义采用了前面这篇文章《自定义IList<T>完整实现》中介绍的IList<T>来实现。
           在开发过程中遇到的问题非常奇怪,将数据绑定后修改数据源不能自动更新在界面中,同时,跟踪调试的时候发现,数据源的非只读操作都会报错,先是数据类型不匹配的错误,采用委托方式进行非只读操作之后又报出线程操作有错误。在网上也无法查到有关资料和介绍,百思不得其解。最终,我认为应该是UI线程的问题。大家要牢记一件事,任何需要UI有响应(例如:改变图片路径导致UI重新加载图片、给TextBox.Text赋值等操作)有改变的操作,必须由UI发起,这种发起只有以下两种方式:
           1、同步方式:
                同步方式指利用某个UI事件的响应程序进行需要UI有响应有改变的操作,比如,我们可以在某个Button的Click事件的处理程序中进行操作,这里的操作有个要求“必须是同步的”,就是说事件处理程序的函数体执行操作之前必须把最终结果计算清楚,然后赋值。
               示例:
            private void stop_Click(object sender, RoutedEventArgs e)
            {           
                this.Sysinfo.text = "Stop_Clicked";
            }
            错误做法:
    private void stop_Click(object sender, RoutedEventArgs e)    
        { 
          (new Thread(new ThreadStart(() => { Dispatcher.BeginInvoke(UILoaded); }))).Start();
    }


    void UILoaded()
    {
    this.Sysinfo.text = "Stop_Clicked";
    }
    在上面的例子里我们能看到,必须要把赋值操作做完,否则,UI是不会响应,如果UI被迫自动响应,
    例如数据绑定的时候,我们还会收到系统报错和程序崩溃。

           2、异步方式:
                在异步方式中,我们之前讲过,如果修改UI的内容必须要发起一个委托,由UI线程进行具体的操作,例如:public delegate void addBudyGroupList(Kernel.Account.BuddyGroupList BGL, object BGObject);使用这样的方式声明一个委托,然后实现委托:
    private void AddBudyGroupListSub(Kernel.Account.BuddyGroupList BGL, object BG)
            {
                BGL.FolderList.Add((Kernel.Account.BuddyGroup)BG);
            }
    使用的方法:
    addBudyGroupList myWB;
    myWB = new addBudyGroupList(AddBudyGroupListSub);
    this.Dispatcher.BeginInvoke(myWB, new Object[] { myFL, (Kernel.Account.BuddyGroup)e.buddyFolderList });
    这里在实际操作数据源的时候采用委托的方式进行就不会报错了,我们可以放心的绑定一个数据源:
    public delegate void setDataSource(DataGrid target, Kernel.Account.BuddyGroupList BGL);
            private void setDataSourceSub(DataGrid target, Kernel.Account.BuddyGroupList BGL)
            {
                target.ItemsSource = BGL.FolderList;
            }

    setDataSource myW = new setDataSource(setDataSourceSub);
    this.Dispatcher.BeginInvoke(myW, new Object[] { this.MyDG, myFL });

    最后总结一下吧,所有涉及UI会发生改变,无论是类似DataBind的自动改变还是类似于“Textbox.text='asd';”之类的手动设置,我们都必须放在UI线程中进行,UI线程是独立于整个应用程序的一个基础线程,所有异步操作或多线程操作都不能直接向UI发送数据修改的请求,必须通过委托的方式发起。

    如果大家还有疑问可以回复,我会尽量及时回复:)

     

    2008年9月9日 3:23