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

Xamarin MVVM中切换开关时如何同步更新模型与数据库?

解决方案:同步MVVM数据与数据库的即时更新

针对开关点击后需立即更新数据库,但直接在实体OnPropertyChanged中操作会导致加载阶段误执行的问题,提供以下三种可行方案:

方案一:ViewModel层监听实体属性变化

在ViewModel中持有Timer实例,订阅其PropertyChanged事件,通过标记判断实体是否完成初始化加载,仅在有效状态下执行数据库更新。

ViewModel代码示例:

public class TimerDetailViewModel : INotifyPropertyChanged
{
    private readonly ITimerRepository _timerRepository;
    private Timer _timer;
    private bool _isLoaded; // 标记实体是否完成初始化

    public Timer Timer
    {
        get => _timer;
        set
        {
            if (_timer != null)
            {
                _timer.PropertyChanged -= Timer_PropertyChanged;
            }
            _timer = value;
            if (_timer != null)
            {
                _timer.PropertyChanged += Timer_PropertyChanged;
                _isLoaded = true; // 实体赋值完成后标记为已加载
            }
        }
    }

    public TimerDetailViewModel(ITimerRepository timerRepository)
    {
        _timerRepository = timerRepository;
    }

    private async void Timer_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // 仅处理IsOnStatus变化,且实体已完成加载
        if (e.PropertyName == nameof(Timer.IsOnStatus) && _isLoaded)
        {
            await _timerRepository.AddOrUpdateTimer(Timer);
            MessagingCenter.Send(this, "saveoccured");
        }
    }

    // 实现INotifyPropertyChanged的必要代码
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

方案二:实体添加初始化标记,通过消息通知ViewModel处理

在Timer实体中添加初始化完成标记,仅在实体初始化完成且IsOnStatus变化时,通过消息通知ViewModel执行数据库操作,避免实体直接依赖Repository。

修改Timer实体:

public class Timer : INotifyPropertyChanged
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    // 新增初始化完成标记
    public bool IsInitialized { get; set; } = false;

    private bool isOnStatus;
    public bool IsOnStatus
    {
        get => isOnStatus;
        set
        {
            isOnStatus = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        
        // 仅在初始化完成且IsOnStatus变化时发送通知
        if (IsInitialized && propertyName == nameof(IsOnStatus))
        {
            MessagingCenter.Send(this, "TimerStatusChanged", this);
        }
    }
}

ViewModel订阅消息处理:

public class TimerDetailViewModel
{
    private readonly ITimerRepository _timerRepository;

    public Timer Timer { get; set; }

    public TimerDetailViewModel(ITimerRepository timerRepository)
    {
        _timerRepository = timerRepository;
        // 订阅实体状态变化消息
        MessagingCenter.Subscribe<Timer, Timer>(this, "TimerStatusChanged", async (sender, timer) =>
        {
            await _timerRepository.AddOrUpdateTimer(timer);
            MessagingCenter.Send(this, "saveoccured");
        });
    }

    // 加载实体后标记初始化完成
    public void LoadTimer(Timer timer)
    {
        Timer = timer;
        Timer.IsInitialized = true;
    }
}

方案三:绑定Switch的Toggled事件到ViewModel命令

放弃双向绑定IsToggled,直接将Switch的Toggled事件绑定到ViewModel的命令,在命令中同步更新实体状态与数据库,完全控制操作时机。

视图代码修改:

<Switch Toggled="{Binding OnStatusToggledCommand}"/>

ViewModel命令实现:

public class TimerDetailViewModel
{
    private readonly ITimerRepository _timerRepository;
    public Timer Timer { get; set; }
    public ICommand OnStatusToggledCommand { get; set; }

    public TimerDetailViewModel(ITimerRepository timerRepository)
    {
        _timerRepository = timerRepository;
        OnStatusToggledCommand = new Command<ToggledEventArgs>(async (args) =>
        {
            Timer.IsOnStatus = args.Value;
            await _timerRepository.AddOrUpdateTimer(Timer);
            MessagingCenter.Send(this, "saveoccured");
        });
    }
}

方案选择建议

  • 方案一适合需要保留双向绑定优势的场景,逻辑集中在ViewModel层,符合MVVM架构原则。
  • 方案三更直接,无需处理属性变化监听,适合逻辑简单的即时操作场景。

内容的提问来源于stack exchange,提问作者Bigyan Chapagain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:18:27