You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 07:03:54