【问题标题】:Xamarin Forms issues with image control. Image does not get renderedXamarin Forms 的图像控制问题。图像未渲染
【发布时间】:2020-05-28 07:18:13
【问题描述】:

我目前正在为移动设备本身制作的图片制作图片预览列表。稍后这些图像将存储在数据库中。然而,在第一次迭代中,我使用来自网络的图像测试列表。我正在使用 xamarin 表单,目标是 android。 That is a picture of the page on the device 我无法确定问题所在。我没有得到任何运行时异常。可能是绑定有问题。

[更新源代码并清理]

这里是视图:

<?xml version="1.0" encoding="utf-8" ?>
<ui:BasePage
    x:Class="AssetManagement.Mobile.Core.UI.OrderItemImageDocumentationPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:actionMenu="clr-namespace:Client.ApplicationDataModel.UI.Controls.ActionMenu;assembly=Client.ApplicationDataModel.UI"
    xmlns:controls="clr-namespace:AssetManagement.Mobile.Core.Controls"
    xmlns:controls1="clr-namespace:UI.XF.Controls;assembly=UI"
    xmlns:res="clr-namespace:AssetManagement.Mobile.Core.Resources"
    xmlns:ui="clr-namespace:AssetManagement.Mobile.Core.UI"
    xmlns:valueconverter="clr-namespace:AssetManagement.Mobile.Core.Classes.ValueConverter"
    xmlns:viewmodel="clr-namespace:AssetManagement.Mobile.Core.ViewModels"
    Title="Bild Dokumentation" 
    x:TypeArguments="viewmodel:OrderItemImageDocuViewModel"><!--{res:Translate OrderItemImageDocumentary}-->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
            <ListView ItemsSource="{Binding OrderItemImages}"
          HasUnevenRows="true"
          ItemSelected="OnListViewItemSelected"
          ItemTapped="OnListViewItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Grid Padding="10">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                           <Image Grid.RowSpan="2"
                           Source="{Binding ImageData}"
                           Aspect="AspectFit"
                           HeightRequest="200"
                           WidthRequest="200" />
                                <Label Grid.Column="1"
                           Text="{Binding Title}"
                           FontAttributes="Bold" />
                                <Label Grid.Row="1"
                           Grid.Column="1"
                           Text="test"
                           VerticalOptions="End" />
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
        <StackLayout Grid.Row="1" Grid.ColumnSpan="3" Grid.Column="0" Orientation="Horizontal">
            <Button x:Name="BtnCancel"
                        AutomationId="BtnCancel"
                        Text="Cancel"
                        Clicked="BtnCancel_OnClicked"
                        Style="{StaticResource DefaultButtonStyle}" />
            <Button x:Name="BtnSave"
                        AutomationId="BtnSave"
                        Text="Save"
                        Clicked="BtnSave_OnClicked"
                        Style="{StaticResource DefaultButtonStyle}" />
        </StackLayout>
    </Grid>



</ui:BasePage>

后面的相关代码:

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class OrderItemImageDocumentationPage : BasePage<OrderItemImageDocuViewModel>
    {
        private IAppConfiguration _appConfig;

        public OrderItemImageDocumentationPage()
        {
            InitializeComponent();
        }

        public OrderItemImageDocumentationPage(OrderItemImageDocuViewModel viewModel, IEventLogService eventLog, ILifetimeScope scope,
            IUserInterfaceService uiService, IAppConfiguration appConfig)
            : base(viewModel, eventLog, scope, uiService)
        {
            InitializeComponent();

            _appConfig = appConfig;
        }

        private void BtnSave_OnClicked(object sender, EventArgs e)
        {
            var test = new OrderItemImageDocData(Title = "test", Xamarin.Forms.ImageSource.FromUri(new Uri(@"https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG")));
            base.ViewModel.OrderItemImages.Add(test);
            base.ViewModel.OrderItemImages.Last().ImageData = Xamarin.Forms.ImageSource.FromUri(new Uri(@"https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG"));
        }
    }

我当前的视图模型:

    public class OrderItemImageDocuViewModel : ApplicationDataBaseViewModel, INavigationEventHandler
    {
        #region Klassenvariablen

        private readonly int _pagingSize = 20;
        private IAppConfiguration _appConfig;
        private ILifetimeScope _scope;
        private IBarcodeParserService _barcodeParser;
        private IEventLogService _eventLog;
        private IUserDataService _userData;
        private int _itemsToLoadCount;
        private ObservableCollection<OrderItemImageDocData> _orderItemImages = new ObservableCollection<OrderItemImageDocData>();
        private OrderItem _orderItemContext = null;
        #endregion Klassenvariablen

        #region Konstruktor

        public OrderItemImageDocuViewModel(ILifetimeScope scope, IDataRepositoryService dataRepository, IBarcodeParserService barcodeParserService, IEventLogService eventLog, IUserDataService userData, ITranslationService translationService, IAppConfiguration appConfig)
            : base(dataRepository)
        {
            _eventLog = eventLog.Initialize(typeof(OrderItemImageDocuViewModel));
            _scope = scope;
            _appConfig = appConfig;
            _userData = userData;
            _barcodeParser = barcodeParserService;
            TranslationService = translationService;

            _itemsToLoadCount = _pagingSize;

            //DatabasesMissing = !dataRepository.IsDataStoreFileAvailable(DownloadDataFileType.TransactionData);

            //if (!DatabasesMissing)
            //{
            //    IsLoading = true;
            //}
        }

        #endregion Konstruktor

        #region Properties

        [NavigationParameter]
        public Order Order { get; set; }

        public IEventLogService EventLog => _eventLog;

        public bool IsLoading { get; set; }

        public bool DatabasesMissing { get; set; }



        public ITranslationService TranslationService { get; set; }

        public IList<OrderItem> OrderItems { get; set; }

        public IOrderTypeScanHandling ScanHandler { get; set; }

        public ObservableCollection<OrderItemImageDocData> OrderItemImages 
        {
            get 
            {
                return _orderItemImages;
            }
            set 
            {
                _orderItemImages = value;
                base.OnPropertyChanged("OrderItemImages");
            }
        }
        #endregion Properties

        public override async void OnNavigationParametersProvided(NavigationContext context)
        {
            if (!DatabasesMissing)
            {
                IsLoading = true;

                try
                {
                    //await InitializeData();

                    //await LoadDataOnDemand();
                }
                catch (Exception ex)
                {
                    //ex.TrackError();
                }

                IsLoading = false;
            }
        }

    }

这是当前保存图像数据的类。这只是一个快速而肮脏的占位符。 由于 vs 设计器相当糟糕并且无法正常工作,我需要一些只提供图像数据的类,这样我就可以按照我想要的方式设计 ui 页面。

    public class OrderItemImageDocData : INotifyPropertyChanged
    {
        #region Events
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        #region Fields
        private string _title = string.Empty;
        private ImageSource _imageData;
        #endregion

        #region Constr
        public OrderItemImageDocData()
        {

        }
        public OrderItemImageDocData(string title, ImageSource imgData) 
        {
            _title = title;
            ImageData = imgData;
        }
        #endregion

        #region Properties
        public string Title 
        {
            get 
            {
                return _title; 
            }
            set 
            {
                _title = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Title"));
            }
        }
        public ImageSource ImageData
        {
            get
            {
                return _imageData;
            }
            set
            {
                _imageData = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("ImageData"));
            }
        }
        #endregion
    }

我在我的 android 清单文件中拥有的权限。

    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.VIBRATE" />

[更新] 我不知道为什么我之前没有注意到它。可能是因为在调试时他没有抛出异常。但是必须有一个运行时异常。每当我尝试添加新的列表视图项(以及新图像)时,vs 输出窗口都会显示此内容:

05-28 08:09:43.563 D/skia    ( 7653): --- SkImageDecoder::Factory returned null
05-28 08:09:43.619 W/art     ( 7653): JNI RegisterNativeMethods: attempt to register 0 native methods for md51558244f76c53b6aeda52c8a337f2c37.CellRenderer_RendererHolder
[0:] ImageLoaderSourceHandler: Could not retrieve image or image data was invalid: Uri: https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG
05-28 08:09:43.703 I/Choreographer( 7653): Skipped 38 frames!  The application may be doing too much work on its main thread.
Thread finished: <Thread Pool> #2

然而,信息相当贫乏。尝试了具有相同输出结果的多个不同图像。

最新更新: 可悲的是,如果其他人有类似的问题,我无法发布此问题的解决方案,请尝试 Mihail Duchev 的答案。他得到了一些很好的指示。但是我从 uri 切换到流源,因为我从数据库加载图像。显然,运行时异常只发生在我使用 uri ImageSource 时。

【问题讨论】:

标签: android image xamarin.forms external


【解决方案1】:

您说得对,问题出在绑定上。 Xamarin 的 Image 类期望 Source 可绑定属性是 ImageSource 实例。来自Images in Xamarin.Forms docs:

Source - 一个 ImageSource 实例,可以是 File、Uri 或 Resource,用于设置要显示的图像。

您当前将图像的源设置为 Image 类型,这对 UI 及其绑定没有任何影响。

你需要做什么,所以改变这个:

Source="{Binding AssetImage}"

到这里:

 Source="{Binding ImageData}"

【讨论】:

  • 已经在尝试绑定“Uri”和“ImageSource”。到目前为止没有任何效果。最新的测试是使用“图像”。我发现一些论坛条目说我需要“位图”。 stackoverflow.com/questions/30850510/…
  • 这很奇怪。此外,您不需要明确地使用位图。
  • 啊,我看到了你的问题。您正在传递 ctor 中的数据,但您正在将其分配给您的 ImageData 属性。我已经更新了我的答案 - 你需要将它绑定到 ImageData 属性,它会起作用。刚刚在我这边试了一下。
  • 在我发布的最新迭代中,我没有通过构造函数分配它。那是我的第一次尝试。我想你可以看到第一篇文章中评论的那一行,我每次点击按钮时都会创建测试条目。我绑定了 ImageData 并通过构造函数传递了 ImageSource。之后我用uri尝试了它,然后我尝试绑定和Image属性作为Source。你试过了,它对你有用吗?
  • 这是您的代码的工作示例。请检查一下,看看你在哪里做错了,然后把它写回到这里。我猜您可能在您的基本页面中错误地设置了绑定上下文? github.com/mduchev/SO_TestImageIssue
【解决方案2】:

但是,在第一次迭代中,我使用来自网络的图像来测试列表。我正在使用 xamarin 表单,目标是 android。

从发布的代码中,图像被设置为绑定到 AssetImage 属性。该属性的类型为Image,将值绑定到图像的源将不起作用。尝试将类型更改为 string

检查代码:

public class OrderItemImageDocData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    ...
    private string _assetImage;
    public string AssetImage
    {
        get
        {
            return _assetImage;
        }
        set
        {
            _assetImage = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("AssetImage"));
        }
    }
}

要从 Web 加载图像,请不要忘记添加 Internet 权限。

【讨论】:

  • 嗨。我在上一篇文章中更新了代码。我删除了“Image”和“Uri”属性。我现在只使用 ImageSource 属性。控制属性“Image.Source”应该没问题吧?还是它真的只接受字符串?我检查了许可,他们似乎没问题。我也将这些添加到了第一篇文章中。
  • ImageSource 属性也应该起作用。现在可以用了吗?
  • 遗憾的是没有。我第一篇文章的更新源不起作用。我将在一个单独的测试应用程序中尝试来自 Mihail Duchev 的测试,并检查它是否在 android v6 设备上工作。如果是这样,我将寻找差异。感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
相关资源
最近更新 更多