绑定List只显示一条记录,绑定BingLidst正常,为什么会这样?

圣殿骑士18 2015-08-25 07:58:04
在开发中,发现一个很奇怪的问题,dataGridView可以绑定很多对象,比如List,但我在开发过程中,却发现将List绑定到dataGridView只显示List中的一条记录。我把List转换成BindingList后,就能显示多条记录,这是为什么?

而且,在这之前我用过很多用List绑定dataGridView的,好像都正常的呀,搞不清楚这是什么特例?
代码如下,请高手帮忙看看:
代码说明:绑定代码在BindData方法中,而BindData是另外一个线程里跨线程调用的

                    if (tagRegistered == null)
{
tagNew.Isvalid = "Normal condition";
}
else ////找到了登记信息,说明异常,报警
{
tagNew.GoodsName = tagRegistered.GoodsName;
tagNew.Isvalid = "Abnormal condition";
this.BeginInvoke(new Action(() => { Alert(); }));
}
listTags.Add(tagNew);
}
}

if (newTags)
{
this.BeginInvoke(new Action(() => { BindData(); }));
}
}

/// <summary>
/// 绑定gridMonitor,设置格式
/// </summary>
private void BindData()
{
this.gridMonitor.AutoGenerateColumns = false;
//疑问:使用List绑定,list中的多条记录,在grid中只能显示1条
//this.gridMonitor.DataSource = listTags;
//转换成BindingList,据能正常显示所有行
this.gridMonitor.DataSource = new BindingList<TagInfoExtend>(listTags);

}
...全文
287 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
圣殿骑士18 2015-08-26
  • 打赏
  • 举报
回复
引用 22 楼 daixf_csdn 的回复:
[quote=引用 17 楼 starfd 的回复:] 或者你在bind方法里面加个console来看下你的事件被触发了多少次,在短时间内
触发几百次,标签1s内能被读取几百次。[/quote] 但BindData方法不会触发几百次,因为我代码里处理为:只有有新标签的时候才触发,所以频率不会很高
圣殿骑士18 2015-08-26
  • 打赏
  • 举报
回复
引用 17 楼 starfd 的回复:
或者你在bind方法里面加个console来看下你的事件被触发了多少次,在短时间内
触发几百次,标签1s内能被读取几百次。
圣殿骑士18 2015-08-26
  • 打赏
  • 举报
回复
引用 20 楼 baidu_23677379 的回复:
[quote=引用 6 楼 daixf_csdn 的回复:] [quote=引用 3 楼 baidu_23677379 的回复:] this.gridMonitor.DataSource = listTags this.gridMonitor.BindData(); // 多這行呢 @@ ? 要有這行才會實際綁定上去吧?
dataGridView控件并没有BindData这个方法[/quote] 因為最早我都用 GridView 後來都改用,自訂性較高的而且比較新的 ListView, 我還以為dataGridView 跟 他們兩個一樣@@ 查了一下 dataGridView看起來是非常舊的東西,要不要考慮換成 ListView >.<" [/quote] 估计你说的是B/S下的开发,才有ListView,我是做WinForm的
baidu_23677379 2015-08-26
  • 打赏
  • 举报
回复
引用 6 楼 daixf_csdn 的回复:
[quote=引用 3 楼 baidu_23677379 的回复:] this.gridMonitor.DataSource = listTags this.gridMonitor.BindData(); // 多這行呢 @@ ? 要有這行才會實際綁定上去吧?
dataGridView控件并没有BindData这个方法[/quote] 因為最早我都用 GridView 後來都改用,自訂性較高的而且比較新的 ListView, 我還以為dataGridView 跟 他們兩個一樣@@ 查了一下 dataGridView看起來是非常舊的東西,要不要考慮換成 ListView >.<"
Forty2 2015-08-26
  • 打赏
  • 举报
回复
引用 楼主 daixf_csdn 的回复:
...... tagNew.Isvalid = "Abnormal condition"; this.BeginInvoke(new Action(() => { Alert(); })); } listTags.Add(tagNew); ......
很有可能通过listTags.Add(tagNew);新增的部分,不能得到显示。 当绑定List<>的时候,只能显示绑定时候现有的数据。由于List<>不提供更新通知(相较于BindingList有更新通知), 后面新增的数据将不能得到更新显示。
  • 打赏
  • 举报
回复
private List<TagInfoExtend> listTags = new List<TagInfoExtend>(); 
private BindingList<TagInfoExtend> bindingListTags = new BindingList<TagInfoExtend>(listTags );

//其它
this.gridMonitor.DataSource = bindingListTags ;
你这个无效是因为你的List根本没赋进去,如果你的List一直变化的话,这里的变化指的是引用地址没变,如果你通过xxx = yyy.ToList()这样是不能监控的,因为引用地址都变了,你要调用BindingList我不知道有没有refresh方法,但bindingsource是有的 你按上面的改动下试试看呢,你只要保证listTags 不会重新进行赋值就可以
  • 打赏
  • 举报
回复
或者你在bind方法里面加个console来看下你的事件被触发了多少次,在短时间内
圣殿骑士18 2015-08-26
  • 打赏
  • 举报
回复
引用 14 楼 starfd 的回复:
你确认是加了lock有效吗? 这跟BindingList<T>两者应该不是一回事吧? lock是多线程导致的问题 BindingList<T>是解决当数据集合发生变化时,同步展示UI部分 如果只是数据集变化需要数据实时变化的话,我想上来就设置数据源为BindingSource,然后BindingSource的DataSource为listTags,然后你的异步线程就是实现listTags的Add和Remove之类的方法
这样我试过了,没有用,还是必须得在硬件事件里调用跨线程调用方法。以下代码将绑定放Load方法里,不管listTags定义成LIst还是BindingList,都没有反应,一条记录都读不出。
private IRFIDReader reader;
        //private List<TagInfoExtend> listTags = new List<TagInfoExtend>();     //记录读取到的标签集合
        private BindingList<TagInfoExtend> listTags = new BindingList<TagInfoExtend>();     //记录读取到的标签集合
        private List<MW_TagDefine> listTagsRegistered;      //将系统登记的所有标签预先载入,以提高判断时的速度
        private string CorpId = ConfigurationManager.AppSettings["CorpId"];

        public FormAntiMonitor()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 窗体载入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormAntiMonitor_Load(object sender, EventArgs e)
        {
            stripBtnStart.Enabled = true;
            stripBtnStop.Enabled = false;

            //取得读写器实例,并连接读写器
            reader = RFIDReaderFactory.GetItemRFIDReader("B433001");

            reader.TagsReportEvent += new TagsReportHandle(reader_TagsReportEvent);

            //加载所有登记的标签
            using (var context = new AMContext())
            {
                listTagsRegistered = context.MW_TagDefine.ToList();
            }
            //设置数据源
            this.gridMonitor.AutoGenerateColumns = false;
            this.gridMonitor.DataSource = listTags;
        }
圣殿骑士18 2015-08-26
  • 打赏
  • 举报
回复
引用 14 楼 starfd 的回复:
你确认是加了lock有效吗? 这跟BindingList<T>两者应该不是一回事吧? lock是多线程导致的问题 BindingList<T>是解决当数据集合发生变化时,同步展示UI部分 如果只是数据集变化需要数据实时变化的话,我想上来就设置数据源为BindingSource,然后BindingSource的DataSource为listTags,然后你的异步线程就是实现listTags的Add和Remove之类的方法
我确认加了lock有效。其他什么也没改,就是加了lock。 wanghui0380说的理由,即差异在于通知接口,也有道理。但测试结果又表明了,也多线程有关。不知该如何解释。
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
没有知道吗,顶下
  • 打赏
  • 举报
回复
你确认是加了lock有效吗? 这跟BindingList<T>两者应该不是一回事吧? lock是多线程导致的问题 BindingList<T>是解决当数据集合发生变化时,同步展示UI部分 如果只是数据集变化需要数据实时变化的话,我想上来就设置数据源为BindingSource,然后BindingSource的DataSource为listTags,然后你的异步线程就是实现listTags的Add和Remove之类的方法
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 12 楼 wanghui0380 的回复:
很简单,因为bindlist实现了数据源更改通知接口,而list没有实现该接口,所以当你在线程里修改数据源的时候,前面一个会通知前面去更改数据(自动刷新),而后面一个则不会通知,你的代码手动刷一下 如果你查看前面的定义,你会发现你继承了IBindinglist接口,同时内部实现了如下两个实现,这就是他和后面那个的区别 // 摘要: // 在将项添加到该列表之前发生。 public event AddingNewEventHandler AddingNew; // // 摘要: // 当列表或列表中的项更改时发生。 public event ListChangedEventHandler ListChanged;
代码手动刷的话是怎么刷呢?
wanghui0380 2015-08-25
  • 打赏
  • 举报
回复
很简单,因为bindlist实现了数据源更改通知接口,而list没有实现该接口,所以当你在线程里修改数据源的时候,前面一个会通知前面去更改数据(自动刷新),而后面一个则不会通知,你的代码手动刷一下 如果你查看前面的定义,你会发现你继承了IBindinglist接口,同时内部实现了如下两个实现,这就是他和后面那个的区别 // 摘要: // 在将项添加到该列表之前发生。 public event AddingNewEventHandler AddingNew; // // 摘要: // 当列表或列表中的项更改时发生。 public event ListChangedEventHandler ListChanged;
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
是不是这么个道理,List<T>是非线程安全的,而BindingList<T>是线程安全的? 但是我查了MSDN,并没有说BindingList是线程安全的。 List: 此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。 只要不修改该集合,List<T> 就可以同时支持多个阅读器。从头到尾对一个集合进行枚举在本质上不是一个线程安全的过程。在枚举与一个或多个写访问竞争的罕见情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。 BindingList: Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 8 楼 starfd 的回复:
还真没见过你这种问题…… listTags会被多线程操作吗?
大牛果然不同凡响,一句话点醒了我,加了锁之后,果然能正常运行! 不过原理是什么呢?
private static object locker = new object();
        /// <summary>
        /// 绑定gridMonitor,设置格式
        /// </summary>
        private void BindData()
        {
            //加了锁,以下代码运行正常!
            lock (locker)
            {
                this.gridMonitor.AutoGenerateColumns = false;
                //疑问:使用List绑定,list中的多条记录,在grid中只能显示1条
                this.gridMonitor.DataSource = listTags;

                //转换成BindingList,就能正常显示所有行
                //this.gridMonitor.DataSource = new BindingList<TagInfoExtend>(listTags);
            }
        }
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 8 楼 starfd 的回复:
还真没见过你这种问题…… listTags会被多线程操作吗?
大牛都没见过,看来真是少见了
  • 打赏
  • 举报
回复
还真没见过你这种问题…… listTags会被多线程操作吗?
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 4 楼 sunny906 的回复:
设置DataSource为List<T>和BindingList<T>都会显示数据源的数据集合;唯一不同的是BindingList<T>可以动态改变数据源
没解决我的问题呀。问题是现象和这个说法对不上,何解?
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 3 楼 baidu_23677379 的回复:
this.gridMonitor.DataSource = listTags this.gridMonitor.BindData(); // 多這行呢 @@ ? 要有這行才會實際綁定上去吧?
dataGridView控件并没有BindData这个方法
圣殿骑士18 2015-08-25
  • 打赏
  • 举报
回复
引用 2 楼 Asa_Jim 的回复:
绑定还用多线程搞啊?
不是绑定非得用多线程,是因为这个是硬件原因,必须得跨UI线程。 但这应该不是问题所在,我不用BeginInvoke一样不行。
加载更多回复(3)

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧