使用MVVM体系结构从SignaturePadView检索图像 [英] Retrieve image from SignaturePadView with MVVM architecture

查看:64
本文介绍了使用MVVM体系结构从SignaturePadView检索图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVVM体系结构中的Prism框架开发Xamarin.Forms应用程序.我需要从屏幕上收集签名,因此我决定包括SignaturePad库.在NuGet中,我包括了Xamarin.Controls.SignaturePad和Xamarin.Controls.SignaturePad.Forms包. 在页面布局(使用XAML构建)中,我具有签名小部件:

I'm developing a Xamarin.Forms application with Prism framework in a MVVM architecture. I need to collect the signature from the screen, so I decided to include the SignaturePad library. With NuGet I included Xamarin.Controls.SignaturePad and Xamarin.Controls.SignaturePad.Forms packages. In page layout (built with XAML) I have the signature widget:

<signature:SignaturePadView 
             x:Name="padView"
             HeightRequest="130"                                
             CaptionText="Sign"
             CaptionTextColor="Black"
             ClearText="Clean"
             ClearTextColor="Black"
             BackgroundColor="White"
             SignatureLineColor="Black"
             StrokeWidth="2"
             StrokeColor="Black"
             BindingContext="{Binding Sign, Mode=TwoWay}" />

在ViewModel中,小部件绑定:

In the ViewModel the widget binding:

private SignaturePadView _sign;
public SignaturePadView Sign
{
    get { return _sign; }
    set { SetProperty(ref _sign, value); }
}

在ViewModel构造函数中:

In the ViewModel constructor:

_sign = new SignaturePadView();

还有一个按钮,在此按钮的动作中,我需要阅读标志图像并将其保存到数据库中.我试过了:

There is also a button, in the action of this button I need to read the sign image and save it to the database. I tried this:

Stream sig = await Sign.GetImageStreamAsync(SignatureImageFormat.Png);
var signatureMemoryStream = sig as MemoryStream;
byte[] data = signatureMemoryStream.ToArray();            

所有这些代码都写在可移植项目中. 不幸的是,它不起作用,因为sig对象始终为null.我认为问题在于小部件绑定,但我不确定.

All this code is written in the portable project. Unfortunately it doesn't work because the sig object is always null. I think that the problem is the widget binding but I'm not sure.

推荐答案

这是使用SignaturePad的另一种方法(这有助于避免将视图放入视图模型中).我本可以使用事件聚合器系统将消息从VM发送到View,但是使用Func对我来说是最简单的解决方案.

Here is another way of working with the SignaturePad (which helps to avoid putting views in your viewmodel). I could have used a event aggregator system to send a message from VM to View but using a Func was a easiest solution for me.

请注意,我根本不使用Prism,所以最终的解决方案可能会有所不同...

Pay attention, I don't use Prism at all, so the final solution could be a bit different...

在未设置BindingContext的情况下,签名视图的XAML部分几乎相同(来自我的文件TestPage.xaml)

The XAML part of the signature view is almost the same without BindingContext set (from my file TestPage.xaml)

<signature:SignaturePadView Margin="-10, 0, -10, 0" 
    x:Name="SignatureView" 
    HorizontalOptions="FillAndExpand" 
    VerticalOptions="FillAndExpand" 
    HeightRequest="150" 
    CaptionText="Signature" 
    CaptionTextColor="Blue" 
    ClearText="Effacer" 
    ClearTextColor="Black" 
    PromptText=""
    PromptTextColor="Green" 
    BackgroundColor="Silver" 
    SignatureLineColor="Black" 
    StrokeWidth="3" 
    StrokeColor="Black" />

在我页面的代码(TestPage.xaml.cs)中

In the codebehind of my page (TestPage.xaml.cs)

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();

        var vm = (TestViewModel)BindingContext; // Warning, the BindingContext View <-> ViewModel is already set

        vm.SignatureFromStream = async () =>
        {
            if (SignatureView.Points.Count() > 0)
            {
                using (var stream = await SignatureView.GetImageStreamAsync(SignaturePad.Forms.SignatureImageFormat.Png))
                {
                    return await ImageConverter.ReadFully(stream);
                }
            }

            return await Task.Run(() => (byte[])null);
        };
    }

ImageConverter.ReadFully(...)只是流到字节转换器

Where ImageConverter.ReadFully(...) is just a stream to byte converter

public static class ImageConverter
{
    public static async Task<byte[]> ReadFully(Stream input)
    {
        byte[] buffer = new byte[16 * 1024];
        using (var ms = new MemoryStream())
        {
            int read;
            while ((read = await input.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            return ms.ToArray();
        }
    }
}

视图模型看起来像这样

public class TestViewModel : ViewModelBase
{
    public Func<Task<byte[]>> SignatureFromStream { get; set; }
    public byte[] Signature { get; set; }

    public ICommand MyCommand => new Command(async () =>
    {
        Signature = await SignatureFromStream();
        // Signature should be != null
    });
}

这篇关于使用MVVM体系结构从SignaturePadView检索图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆