Xamarin:byte[]绑定Grid标签,Timer更新时OnPropertyChanged未触发求助
解决byte[]绑定GridView标签不更新的问题
我来帮你搞定这个绑定更新的问题!核心原因其实很简单:byte[]是引用类型,你之前能成功绑定单个byte是因为它是值类型,赋值时会触发属性的setter进而调用OnPropertyChanged();但对于数组,如果你只是修改数组里的元素,而没有改变数组本身的引用,属性的setter根本不会被执行,自然不会通知UI更新。
下面给你几种可行的解决方案,按需选择:
方案1:修改数组元素后重新赋值数组(触发setter通知)
这种方法不用改属性类型,每次修改元素时,先克隆原数组,修改克隆后的数组,再把克隆数组赋值给RecvData,这样就能触发setter里的OnPropertyChanged()。
示例代码:
// 假设你的Timer事件处理逻辑是这样的 testtimer.Elapsed += (sender, e) => { // 注意:System.Timers.Timer的事件在非UI线程,需要切回UI线程更新属性 Application.Current.Dispatcher.Invoke(() => { // 克隆原数组,避免直接修改原引用 var updatedData = (byte[])_recvdata.Clone(); // 修改数组元素 updatedData[0] = 0x01; updatedData[1] = 0x02; // 重新赋值,触发setter和PropertyChanged RecvData = updatedData; }); }; // 你的RecvData属性保持原来的写法即可 public byte[] RecvData { get { return _recvdata; } set { if (_recvdata != value) { _recvdata = value; OnPropertyChanged(nameof(RecvData)); } } }
方案2:用ObservableCollection替代byte[]
如果你的场景需要频繁修改数组元素,推荐直接用ObservableCollection<byte>——它本身实现了INotifyCollectionChanged接口,修改元素时会自动通知UI更新,不用手动触发OnPropertyChanged()。
示例代码:
// 把byte[]换成ObservableCollection<byte> private ObservableCollection<byte> _recvData; public ObservableCollection<byte> RecvData { get => _recvData; set { if (_recvData != value) { _recvData = value; OnPropertyChanged(nameof(RecvData)); } } } // 初始化时创建集合(比如长度为8的byte集合) public YourViewModel() { RecvData = new ObservableCollection<byte>(new byte[8]); testtimer = new System.Timers.Timer(1000); testtimer.Elapsed += Timer_Elapsed; testtimer.Start(); } private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Application.Current.Dispatcher.Invoke(() => { // 直接修改集合元素,UI会自动更新 RecvData[0] = (byte)(RecvData[0] + 1); RecvData[1] = 0xFF; }); }
方案3:手动触发PropertyChanged通知
如果必须保留byte[]类型,也可以在修改数组元素后,手动调用OnPropertyChanged()来通知UI更新,不用重新赋值数组:
示例代码:
testtimer.Elapsed += (sender, e) => { Application.Current.Dispatcher.Invoke(() => { // 直接修改数组元素 _recvdata[0] = 0x0A; _recvdata[2] = 0x0B; // 手动触发通知,告诉UI RecvData属性已经变化 OnPropertyChanged(nameof(RecvData)); }); };
额外注意点
一定要记得:System.Timers.Timer的Elapsed事件是在后台线程触发的,直接在这个线程里更新UI绑定的属性会导致跨线程异常,所以必须用Dispatcher.Invoke(WPF)或者Control.Invoke(WinForms)切换回UI线程再执行属性更新操作。
内容的提问来源于stack exchange,提问作者zyyphilip
相关产品推荐
相关产品推荐

