在没有设备渲染器的情况下创建Xamarin自定义图像

时间:2017-12-21 15:17:16

标签: c# wpf xaml xamarin xamarin.forms

我尝试创建一个基于Xamarin表单的Image,它可以绑定一个字节数组。

我不想直接在我的ModelView中使用ImageSource,因为ModelViews也用于WPF UI。 所以我只想将字节数组(从base64字符串创建)转换为可以由UI绑定的图像。在WPF端没有问题,因为它可以采用bytearray格式的图像。现在我想为Xamarin Forms创建一个Custom-ImageControll,它可以接受/绑定一个字节数组并将其格式化为ImageSource。

此外,我不想为每个平台创建一个渲染器。我想使用Xamarin Image的标准渲染器。

如下所示,我创建了一个自定义图像(MVVMImage)并使用了Xamarin提供的基本图像。

问题是每次MVVMImage加载时我得到:System.Reflection.TargetInvocationException: <Timeout exceeded getting exception details>

自定义图片:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Forms;

   namespace Testape
   {
      public class MVVMImage : Image
      {

          public MVVMImage() : base()
          {
            //Attempt to avoid of create renderer on every device. 
          }

          public static readonly BindableProperty ArraySourceProperty =
          BindableProperty.Create(nameof(ArraySource), typeof(byte[]), typeof(MVVMImage), "");

          public byte[] ArraySource
          {
              set
              {
                  this.Source = ImageSource.FromStream(() => new   MemoryStream(value));
              }
          }
      }
  }

MainPage 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:local="clr-namespace:Testape;assembly=Testape"
             x:Class="Testape.MainPage">

    <local:MVVMImage ArraySource="{Binding Img}"
           VerticalOptions="Center"
           HorizontalOptions="Center"/>
</ContentPage>

MainPage代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace Testape
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            byte[] bt = Convert.FromBase64String("iVBORw0KGgoAAA< And so on >AAAAAElFTkSuQmCC");
            BindingContext = new ViewModelMainw(bt);
        }
    }
}

模型视图

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace Testape
{
    public class ViewModelMainw
    {
        byte[] bffapt;
        public ViewModelMainw(byte[] bff)
        {
            bffapt = bff;
        }
        public byte[] Img
        {
            get { return bffapt; }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

一个问题是您处理可绑定属性更改的方式。

应该在属性更改而不是setter中处理。

它应该是这样的:

public static readonly BindableProperty ArraySourceProperty =
    BindableProperty.Create(nameof(ArraySource), typeof(byte[]), typeof(MVVMImage), null,
    BindingMode.OneWay, null, OnArraySourcePropertyChanged);

public byte[] ArraySource
{
    get { return (byte[])GetValue(ArraySourceProperty); }
    set { SetValue(ArraySourceProperty, value); }
}

private static void OnArraySourcePropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
    var control = (MVVMImage) bindable;
    if (control != null)
    {
        control.Source = ImageSource.FromStream(() => new  MemoryStream((byte[])newvalue));
    }
}