none
datagrid委托添加数据 RRS feed

  • 问题

  • datagrid 绑定了数据, 在委托中修改数据是没问题的, 但是如果删除或者添加数据则会报datagrid的线程问题, 如何做可以在委托中增加数据?

    <DataGrid DockPanel.Dock="Bottom" Name="datagrid" CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False" HeadersVisibility="Column" SelectionMode="Single" >
            <DataGrid.Columns>
                    <DataGridTextColumn Header="AA" Binding="{Binding AA}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="BB" Binding="{Binding BB}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="CC" Binding="{Binding CC}" />
                    <DataGridTextColumn Header="DD" Binding="{Binding DD}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="EE"  Binding="{Binding EE}" IsReadOnly="True"/>
            </DataGrid.Columns>
    </DataGrid>

    ObservableCollection<DATADefine> items = new ObservableCollection<DATADefine>();
    
    datagrid.ItemsSource = items;
    
    //不用委托可以添加数据
    items.Add(new DATADefine());
    
    
    
    //用委托会报线程问题
    delegate void Del(DATADefine o);
    
    Del del = AddDATA;
    del.BeginInvoke(one, null, null);
    
    void AddDATA(DATADefine o)
    {
          items.Add(o);
    }

    2015年5月25日 2:35

全部回复

  • WPF跨线程访问控件应该使用如下代码来访问

    datagrid.Dispatcher.BeginInvoke(() =>
                {
    
                });

    以下为该成员的相关资料

    https://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcher(v=vs.110).aspx

    2015年5月25日 2:53
  • 这个我试过, 这样会阻塞主线程
    2015年5月25日 4:33
  • Hi Neo Xiao,

    我根据你的代码,运行了一下,提示的异常信息是:“This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.”

    这说明你所实例化的那个委托,调用它的"BeginInvoke()"方法生成了一个新的线程,与WPF的UI线程不一样,因此你在自己的线程里调用另一个线程中的"item"会出现跨线程访问的问题,这里我给出的解决方案是将“item.add()”放在“Dispatcher.Invoke()”中,代码如下:

    ObservableCollection<DATADefine> items = new ObservableCollection<DATADefine>();
            delegate void Add(DATADefine o);
            public MainWindow()
            {
                InitializeComponent();
                datagrid.ItemsSource = items;
    
                
                Add add = AddDATA;
                add.BeginInvoke(new DATADefine {AA="aa",BB="bb",CC="cc",DD="dd",EE="ee" }, null, null);
            }
    
            
    
            void AddDATA(DATADefine o)
            {
                Dispatcher.Invoke(new Action(() => {
                    items.Add(o);
                }));
            }

    Best Regards,

    Xavier Eoro


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年5月26日 2:54
    版主
  • 这种机制就是要向主线程中插入运行代码来保证线程安全,里面的方法肯定会运行在主线程中。

    向一个集合添加对象应该阻塞主线程的时间可以忽略吧,除非你有其他耗时的代码。

    2015年5月26日 5:36
  • Hi Xavier

    根据你的写法我发现的确可以, 但是却没有达到我的目的, 我的目的是为了防止前台UI进程阻塞, 而使用Dispatcher.Invoke方法会阻塞主线程而使UI假死. 以前考虑过用backgroundworker, 但是因为不方便传入变量而没有采用.

    以下是我试验的代码

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                datagrid.ItemsSource = items;
            }
    
            ObservableCollection<DATADefine> items = new ObservableCollection<DATADefine>();
            delegate void Del();
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Del del = Add;
                del.BeginInvoke(null, null);
            }
    
            void Add()
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    System.Threading.Thread.Sleep(1000);
                    items.Add(new DATADefine() { AA = "11", BB = "22" });
                    System.Threading.Thread.Sleep(1000);
                    items.Add(new DATADefine() { AA = "33", BB = "44" });
                }));
            }
        }
    
        public class DATADefine
        {
            public string AA
            {
                get;
                set;
            }
            public string BB
            {
                get;
                set;
            }
        }
    


    • 已编辑 Neo Xiao 2015年5月27日 12:55 修改代码
    2015年5月27日 12:50
  • Hi Neo,

    WPF只是不允许跨线程访问程序,并非不允许多线程更新界面。你可以将耗时的部分单独开一个线程来处理,在那个线程中进行更新操作,此时就不会影响到主线程。MSDN上有篇文章介绍了详细的操作:Multithreaded UI: HostVisual:http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx

    Best Regards,

    Xavier Eoro


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年6月4日 6:35
    版主