【问题标题】:How do I use Xamarin.Essentials MediaPicker with MVVM and DataBinding如何将 Xamarin.Essentials MediaPicker 与 MVVM 和 DataBinding 一起使用
【发布时间】:2021-08-26 06:41:34
【问题描述】:

我正在尝试在我的应用程序中拍摄照片,因为这需要在不同的页面上实现,我需要它在 MVVM 架构中工作。当我在后面的相机页面代码上测试它时,它工作得非常好,但是一旦我实现 DataBinding 和 MVVM,模拟器相机就无法初始化。我没有收到任何构建或部署错误,也不知道从哪里开始寻找。该文档没有太大帮助。每次打开应用程序时都需要保存和重复使用捕获的图像 - 或许要记住这一点。

这是我的 ViewModel:

using System.Collections.Generic;
using System.Text;
using Xamarin.Essentials;
using Xamarin.Forms;
using XamCam.Views;
using MvvmHelpers;
using System.ComponentModel;
using System.Windows.Input;

namespace XamCam.ViewModels
{
    public class CameraViewModels : BaseViewModel
    {
        public CameraViewModels()
        {
            TakePhoto = new Command(OnTakePhoto);
        }

        public ICommand TakePhoto { get; }

        private Image image; // = new Image();
        public Image CamImage
        {
            get => image;
            set
            {
                if (image == value)
                    return;
                image = value;
                OnPropertyChanged();
            }
        }

        async void OnTakePhoto()
        {
            var result = await MediaPicker.CapturePhotoAsync();

            if (result != null)
            {
                var stream = await result.OpenReadAsync();

                image.Source = ImageSource.FromStream(() => stream);
            }
        }
    }
}

这是我的视图 XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:viewmodels="clr-namespace:XamCam.ViewModels" 
             x:DataType="viewmodels:CameraViewModels"
             x:Class="XamCam.Views.Camera"
             BackgroundColor="AliceBlue">
    <ContentPage.BindingContext>
        <viewmodels:CameraViewModels/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout BindingContext="CameraViewModel">
            <Label Text="Welcome to The XamCam!" />
            <Button Text="Take Photo"
                    Command="{Binding TakePhoto}"/>
            <Image BindingContext="{Binding CamImage}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

我怀疑这与我的 CamImage 属性有关,但我对此很陌生,我不确定这是否是绑定媒体对象的正确方法。

【问题讨论】:

  • MediaPicker 文档中有一个重要提示:“所有方法都必须在 UI 线程上调用,因为权限检查和请求由 Xamarin.Essentials 自动处理。”
  • 为什么会在非 UI 线程 @Jason 上触发命令?
  • 也许我错了 - 但我没有看到它记录了命令总是在主线程上。
  • @Jason 我接受了这一点,因为我的知识非常初级,我不确定这是否以及如何受到 MVVM 的影响。我的理解是它仍然在主线程上运行,但业务逻辑只是简单地封装在其他地方。不知道我的理解是否正确。

标签: c# android xamarin mvvm data-binding


【解决方案1】:

我怀疑这与我的 CamImage 属性有关,但我对此很陌生,我不确定这是否是绑定媒体对象的正确方法。

我建议你可以在 CameraViewModels 中添加ImageSource1 属性,而不是Image 属性。

public class CameraViewModels : INotifyPropertyChanged
{
    public CameraViewModels()
    {
        TakePhoto = new Command(OnTakePhoto);
    }

    public ICommand TakePhoto { get; }

    private ImageSource image;
    public ImageSource CamImage
    {
        get => image;
        set
        {
            if (image == value)
                return;
            image = value;
            RaisePropertyChanged("CamImage");
        }
    }

    async void OnTakePhoto()
    {
        var result = await Xamarin.Essentials.MediaPicker.CapturePhotoAsync();

        if (result != null)
        {
            var stream = await result.OpenReadAsync();

            CamImage = ImageSource.FromStream(() => stream);
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;


    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

<ContentPage
x:Class="App1.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App1">
<ContentPage.BindingContext>
    <local:CameraViewModels />
</ContentPage.BindingContext>

<StackLayout>
    <StackLayout>
        <Label Text="Welcome to The XamCam!" />
        <Button Command="{Binding TakePhoto}" Text="Take Photo" />
        <Image Source="{Binding CamImage}" />
    </StackLayout>
</StackLayout>

【讨论】:

  • 这种方式更有意义,但由于某些奇怪的原因,相机仍然无法启动。我开始怀疑相机是否仅通过点击事件而不是命令启动。不知道为什么。
  • @JC_vd_Merwe_03 根据您的代码,您通过Button.click启动相机,我将TakePhoto命令绑定到Button.command,我可以打开相机并且没有问题,您试试我的代码吗?还有问题吗?
  • 我试过你的代码,就像我在评论中说的那样,相机仍然没有启动。问题必须在其他地方,因为所有迹象表明它应该起作用。打算尝试一个新项目,看看是否会有所作为。会让你知道的。
  • @JC_vd_Merwe_03 太奇怪了,因为我使用我的代码,一切正常,我可以成功启动相机。如果您有任何更新,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-02
  • 1970-01-01
相关资源
最近更新 更多