gpt4 book ai didi

c# - 寻找有关如何在 MVVM C#​​ Xamarin 中实现 "volume"属性的建议

转载 作者:行者123 更新时间:2023-12-03 10:57:51 24 4
gpt4 key购买 nike

所以我正在开发一个可以调整(除其他外)设备音量的应用程序。所以我开始的是一个非常简单的模型,它实现了 INotifyPropertyChanged。据我所知,在如此简单的场景中不需要 ViewModel。设置音量属性时调用 INPC,Model 生成 TCP 消息告诉设备改变音量。

然而,这就是它变得复杂的地方。音量不必由应用程序更改,也可以直接在设备上更改,甚至可以通过另一部装有该应用程序的手机进行更改。从设备获取这些更改的唯一方法是定期轮询它。

所以我认为合理的是稍微改变结构。所以现在我有一个代表实际设备的 DeviceModel。我添加了一个 VolumeViewModel。 DeviceModel 类现在处理生成 TCP 消息。它还定期轮询设备。但是,假设 DeviceModel 发现音量发生了变化。这应该如何传播回 VolumeViewModel 以便所有更改都是从 UI 和实际设备双向进行的?如果我将 INPC 放在 DeviceModel 中,我的 VolumeViewModel 似乎就变得多余了。也许对于这个简单的人为示例很好,但可以说该设备比仅 1 卷更复杂。我在想 VM 可以包含对模型的引用,而卷属性可能只是对 DeviceModel 中的卷的引用,但它仍然不能真正解决我的问题。

如果 DeviceModel 卷发生更改,则引用不会更改,因此在我看来,这不会触发 VolumeViewModel 中卷属性的 setter 函数。当轮询看到不同的卷时,我是否让 ViewModel 将事件处理程序注入(inject)到要调用的模型中?我是否在两者中都使用 INPC(以这种方式实现它会是什么样子?)

最佳答案

设定方向明确。你想明确地得到它。所以我们需要类似的东西

class MyDeviceService : IDeviceService
{
public async Task SetVolumeAsync(int volume) { }
public async Task<int> GetVolumeAsync() { }
}

// ViewModel
class DeviceViewModel : INotifyPropertyChanged
{
public int Volume { get{ ... } set { ... } }
public DeviceViewModel(IDeviceService service) { ... }
}

对于更新,您有不同的选择:

回电

亲:
  • 易于实现

  • 骗子:
  • 只有一个订阅者
  • 看起来像是一个糟糕的事件实现(在我们的场景中)

  • class MyDeviceService
    {
    public Action<int> VolumeChangedCallback { get; set; }
    public async Task SetVolumeAsync(int volume) { }
    public async Task<int> GetVolumeAsync() { }

    // producer
    VolumeChangedCallback(newVolume);
    }

    // consumer
    myDeviceService.VolumeChangedCallback = v => Volume = v;

    // deregistration
    myDeviceService.VolumeChangedCallback = null;

    事件

    亲:
  • 语言功能(内置)
  • 多个订阅者

  • 骗子:
  • ???

  • class MyDeviceService
    {
    public event EventHandler<VolumeChangedEventArgs> VolumeChanged;
    public async Task SetVolumeAsync(int volume) { }
    public async Task<int> GetVolumeAsync() { }

    // producer
    VolumeChanged(new VolumeChangedEventArgs(newVolume));
    }

    // consumer
    MessagingCenter.Subscribe<MyDeviceService, int>(this,
    MyDeviceService.VolumeMessageKey, newVolume => Volume = newVolume);

    // needs deregistration
    MessagingCenter.Unsubscribe<MyDeviceService, int>(this,
    MyDeviceService.VolumeMessageKey, newVolume => Volume = newVolume);

    留言

    亲:
  • 轻松订阅/取消订阅
  • 多个订阅者
  • 多个发件人
  • 接收方不需要知道发送方

  • 骗子:
  • 需要外部库(但包含在 Xamarin.Forms、MvvMCross、其他 MvvM 框架中)

  • class MyDeviceService
    {
    public static string VolumeMessageKey = "Volume";
    public async Task SetVolumeAsync(int volume) { }
    public async Task<int> GetVolumeAsync() { }

    // producer
    MessagingCenter.Send<MyDeviceService, int>(this,
    VolumeMessageKey, newVolume);
    }

    // consumer
    MessagingCenter.Subscribe<MyDeviceService, int>(this,
    MyDeviceService.VolumeMessageKey, newVolume => Volume = newVolume);

    // needs deregistration
    MessagingCenter.Unsubscribe<MyDeviceService, int>(this,
    MyDeviceService.VolumeMessageKey, newVolume => Volume = newVolume);

    可观察

    使用 Reactive extensions总是很好,如果你有事件流。

    亲:
  • 轻松订阅/取消订阅
  • 多个订阅者
  • 可过滤,如 IEnumerable (例如 Where(volume => volume > 10) )

  • 骗子:
  • 仅用于一种情况的外部库
  • 全新方法带来的高学习努力

  • class MyDeviceService
    {
    IObservable<int> VolumeUpdates { get; }
    public async Task SetVolumeAsync(int volume) { }
    public async Task<int> GetVolumeAsync() { }
    }

    // consumer
    _volumeSubscription = myDeviceService.VolumeUpdates
    .Subscribe(newVolume => Volume = newVolume);

    // deregistration
    // - implicitly, if object gets thrown away (but not deterministic because of GC)
    // - explicitly:
    _volumeSubscription.Dispose();

    结论

    我在模型中省略了 INPC,因为那是事件,但更糟糕的是,因为您必须比较属性名称。
    如果您查看这些示例,您会发现,它们只是订阅和取消订阅的方式不同。主要区别在于它们提供的灵 active 。就个人而言,我会选择响应式扩展;)但事件和消息传递也很好。因此,请选择您和您的团队成员最了解的方法。你只需要记住:

    总是注销! ^^

    关于c# - 寻找有关如何在 MVVM C#​​ Xamarin 中实现 "volume"属性的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36584825/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com