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

如何将Xamarin中CameraView捕获逻辑的后置代码转换为MVVM模式

Xamarin 后置代码转MVVM风格实现方案

核心实现逻辑

  • 移除所有直接操作控件属性的逻辑,全部迁移到ViewModel层处理
  • 将所有需要动态更新的视图属性,封装为ViewModel中支持属性变更通知的可绑定属性
  • 通过事件转命令的方式,将CameraView的MediaCaptured事件绑定到ViewModel的处理命令,直接透传事件参数作为入参

步骤1:编写ViewModel代码

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.CommunityToolkit.ObjectModel;
// 按需引入你的项目其他命名空间

public class CameraViewModel : INotifyPropertyChanged
{
    #region 可绑定属性
    private CameraCaptureMode _captureMode;
    public CameraCaptureMode CaptureMode
    {
        get => _captureMode;
        set => SetProperty(ref _captureMode, value);
    }

    private bool _isPreviewVideoVisible;
    public bool IsPreviewVideoVisible
    {
        get => _isPreviewVideoVisible;
        set => SetProperty(ref _isPreviewVideoVisible, value);
    }

    private bool _isPreviewPictureVisible;
    public bool IsPreviewPictureVisible
    {
        get => _isPreviewPictureVisible;
        set => SetProperty(ref _isPreviewPictureVisible, value);
    }

    private int _previewPictureRotation;
    public int PreviewPictureRotation
    {
        get => _previewPictureRotation;
        set => SetProperty(ref _previewPictureRotation, value);
    }

    private ImageSource _previewPictureSource;
    public ImageSource PreviewPictureSource
    {
        get => _previewPictureSource;
        set => SetProperty(ref _previewPictureSource, value);
    }

    private MediaSource _previewVideoSource;
    public MediaSource PreviewVideoSource
    {
        get => _previewVideoSource;
        set => SetProperty(ref _previewVideoSource, value);
    }

    private string _doCameraThingsButtonText;
    public string DoCameraThingsButtonText
    {
        get => _doCameraThingsButtonText;
        set => SetProperty(ref _doCameraThingsButtonText, value);
    }
    #endregion

    public ICommand MediaCapturedCommand { get; }

    public CameraViewModel()
    {
        MediaCapturedCommand = new AsyncCommand<MediaCapturedEventArgs>(OnMediaCaptured);
    }

    private Task OnMediaCaptured(MediaCapturedEventArgs e)
    {
        switch (CaptureMode)
        {
            case CameraCaptureMode.Default:
            case CameraCaptureMode.Photo:
                IsPreviewVideoVisible = false;
                IsPreviewPictureVisible = true;
                PreviewPictureRotation = e.Rotation;
                PreviewPictureSource = e.Image;
                DoCameraThingsButtonText = "Snap Picture";
                break;
            case CameraCaptureMode.Video:
                IsPreviewPictureVisible = false;
                IsPreviewVideoVisible = true;
                PreviewVideoSource = e.Video;
                DoCameraThingsButtonText = "Start Recording";
                break;
        }
        return Task.CompletedTask;
    }

    #region INotifyPropertyChanged 基础实现
    public event PropertyChangedEventHandler PropertyChanged;
    protected bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        return true;
    }
    #endregion
}

如果你使用CommunityToolkit.Mvvm等MVVM工具包,可以通过源生成器大幅简化属性和命令的样板代码。

步骤2:配置XAML绑定

这里提供两种绑定方案可选:

方案A:使用EventToCommand行为(无后置代码)

依赖Xamarin Community Toolkit的行为实现,页面完全没有后置业务代码:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
             xmlns:local="clr-namespace:你的项目命名空间"
             x:Class="你的项目命名空间.CameraPage">
    <ContentPage.BindingContext>
        <local:CameraViewModel />
    </ContentPage.BindingContext>

    <StackLayout>
        <CameraView x:Name="cameraView"
                    CaptureMode="{Binding CaptureMode}">
            <CameraView.Behaviors>
                <xct:EventToCommandBehavior 
                    EventName="MediaCaptured"
                    Command="{Binding MediaCapturedCommand}"
                    EventArgsParameterPath="." />
            </CameraView.Behaviors>
        </CameraView>

        <Image x:Name="previewPicture"
               IsVisible="{Binding IsPreviewPictureVisible}"
               Rotation="{Binding PreviewPictureRotation}"
               Source="{Binding PreviewPictureSource}" />

        <MediaElement x:Name="previewVideo"
                      IsVisible="{Binding IsPreviewVideoVisible}"
                      Source="{Binding PreviewVideoSource}" />

        <Button x:Name="doCameraThings"
                Text="{Binding DoCameraThingsButtonText}" />
    </StackLayout>
</ContentPage>

方案B:极简后置代码转发(无需引入第三方库)

如果不想引入第三方行为库,也可以在后置代码中仅做参数转发,同样符合MVVM职责分离要求:
页面后置代码:

void CameraView_MediaCaptured(object sender, MediaCapturedEventArgs e)
{
    (BindingContext as CameraViewModel)?.OnMediaCaptured(e);
}

XAML中不需要配置行为,其余控件的绑定和方案A完全一致即可。

内容的提问来源于stack exchange,提问作者Reymart Balibad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:42:00