如何在 Prism (MVVM) 中使用 Windows.Devices.Enumeration.DevicePicker?

How to use Windows.Devices.Enumeration.DevicePicker with Prism (MVVM)?

我正在开发一个新的 UWP 应用程序,它通过蓝牙与某些硬件进行交互。使用 windows-universal-samples repo 作为指南,我能够成功地获得我想要的工作。

现在我正在尝试使用 Prism 将我在点击事件处理程序中编写的代码重构为视图模型 class。但是我不知道如何处理这个。在我需要在 View 和 ViewModel 之间传递数据的其他场景中,我会在 ViewModel 上创建一个 属性 并将其绑定到视图 XAML.

中的控件

问题是 Windows.Devices.Enumaration.DevicePicker 的使用方式似乎与 MVVM 模式不兼容。在点击处理程序中,数据和控件合并在一起,我不知道如何在视图模型上制作某种列表 属性,然后将其绑定到视图。这是我正在使用的代码的最简单示例:

async void DiscoverButton_OnClick(object sender, RoutedEventArgs e)
{
    var devicePicker = new DevicePicker();
    devicePicker.Filter.SupportedDeviceSelectors.Add(BluetoothLEDevice.GetDeviceSelectorFromPairingState(true));

    // Calculate the position to show the picker (right below the buttons)
    var ge = DiscoverButton.TransformToVisual(null);
    var point = ge.TransformPoint(new Point());
    var rect = new Rect(point, new Point(100, 100));
    var device = await devicePicker.PickSingleDeviceAsync(rect);

    var bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
}

参见PickSingleDeviceAsync()直接创建控件。

Now I am trying to refactor the code I wrote in a click event handler into a view model class using Prism. However I don't know how to approach this.

您可以为按钮绑定命令,并使用 CommandParameter 将参数传递给命令。

详情请参考以下代码示例:

<Button x:Name="btn" Content="device" Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=btn}"></Button>
public class MianViewModel : BindableBase
{
    public ICommand ClickCommand
    {
        get;
        private set;
    }

    public MianViewModel()
    {
        ClickCommand = new DelegateCommand<object>(ClickedMethod);
    }

    private async void ClickedMethod(object obj)
    {
        var devicePicker = new DevicePicker();
        devicePicker.Filter.SupportedDeviceSelectors.Add(BluetoothLEDevice.GetDeviceSelectorFromPairingState(true));

        // Calculate the position to show the picker (right below the buttons)
        Button DiscoverButton = obj as Button;
        if (DiscoverButton != null)
        {
            var ge = DiscoverButton.TransformToVisual(null);
            var point = ge.TransformPoint(new Point());
            var rect = new Rect(point, new Point(100, 100));
            var device = await devicePicker.PickSingleDeviceAsync(rect);

            if (device != null)
            {
                var bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
            }
        }
    }
}

我想出的解决方案是放弃 DevicePicker 提供的内置 UI,而是创建我自己的 UI 以与 DeviceWatcher 一起使用。例如:

void StartWatcher()
{
    ResultCollection.Clear();

    string selector = BluetoothLEDevice.GetDeviceSelector();

    DeviceWatcher = DeviceInformation.CreateWatcher(selector);

    DeviceWatcher.Added += async (deviceWatcher, deviceInformation) =>
    {
        await OnUiThread(() =>
        {
            ResultCollection.Add(deviceInformation);
        });
    };

    DeviceWatcher.Start();
}

其中 ResultCollection 将从视图模型绑定到视图。