使用MVVM体系结构从SignaturePadView检索图像

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

 

在ViewModel中,小部件绑定:

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

在ViewModel构造函数中:

 _sign = new SignaturePadView(); 

还有一个按钮,在这个按钮的动作中我需要读取符号图像并将其保存到数据库中。 我试过这个:

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

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

以下是使用SignaturePad的另一种方法(有助于避免在viewmodel中放置视图)。 我本可以使用事件聚合器系统从VM向View发送消息,但使用Func对我来说是最简单的解决方案。

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

签名视图的XAML部分几乎没有BindingContext设置(来自我的文件TestPage.xaml)

  

在我的页面的代码隐藏(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(…)只是一个到字节转换器的流

 public static class ImageConverter { public static async Task 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> SignatureFromStream { get; set; } public byte[] Signature { get; set; } public ICommand MyCommand => new Command(async () => { Signature = await SignatureFromStream(); // Signature should be != null }); }