2017-08-30 28 views
1

我正在MVVM體系結構中使用Prism框架開發Xamarin.Forms應用程序。我需要從屏幕上收集簽名,所以我決定加入SignaturePad庫。使用NuGet,我包含了Xamarin.Controls.SignaturePad和Xamarin.Controls.SignaturePad.Forms包。 在頁面佈局(與XAML建)我有簽名控件:使用MVVM體系結構從SignaturePadView中檢索圖像

<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}" /> 

在視圖模型的部件結合:

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

在視圖模型構造:

_sign = new SignaturePadView(); 

有也是一個按鈕,在這個按鈕的動作中,我需要讀取符號圖像並將其保存到數據庫中。我試過這個:

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

所有這些代碼都寫在便攜式項目中。 不幸的是,它不起作用,因爲sig對象始終爲空。我認爲問題在於小部件綁定,但我不確定。

回答

1

這是另一種使用SignaturePad的方法(它有助於避免在視圖模型中放置視圖)。我本可以使用事件聚合器系統從VM發送消息到View,但使用Func對我來說是最簡單的解決方案。

注意的是,我不使用棱鏡可言,所以最終的解決方案可能是一個有點不同......

簽名視圖的XAML部分幾乎是沒有的BindingContext集相同(從我的文件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)

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<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 
    }); 
} 
+1

感謝您的幫助。它也適用於Prism。只是澄清:SignatureView.Points是一個IEnumerable 並不支持計數。 – TeoVr81

+0

@ TeoVr81如果我記得,伯爵的作品感謝林格 – hugoterelle

+0

你是對的,如果我包括System.Linq它沒有其他解決方法工作正常。謝謝大家! – TeoVr81