如何将 Xamarin.Essentials MediaPicker 与 MVVM 和 DataBinding 一起使用
Posted
技术标签:
【中文标题】如何将 Xamarin.Essentials MediaPicker 与 MVVM 和 DataBinding 一起使用【英文标题】:How do I use Xamarin.Essentials MediaPicker with MVVM and 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 的影响。我的理解是它仍然在主线程上运行,但业务逻辑只是简单地封装在其他地方。不知道我的理解是否正确。 【参考方案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 太奇怪了,因为我使用我的代码,一切正常,我可以成功启动相机。如果您有任何更新,请告诉我。以上是关于如何将 Xamarin.Essentials MediaPicker 与 MVVM 和 DataBinding 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Xamarin Essentials Share 将应用程序链接共享给其他用户并在他们单击后打开应用程序?
Xamarin Essentials教程安全存储SecureStorage
Xamarin.Forms - 使用 Xamarin.Essentials 在两个坐标之间获取里程