【问题标题】:Xaml - how to use ImageSource from ViewModelXaml - 如何使用 ViewModel 中的 ImageSource
【发布时间】:2019-05-26 11:46:19
【问题描述】:

我有一个ObservableCollection<Item> 和一个Item 包含磁盘中某些图像的文件路径和ImageSource

public ObservableCollection<Item> Items { get; set; } = new ObservableCollection<MediaListItem>();
public class Item
{
    public string Image { get; set; } // Full path to the image
    public ImageSource ImageSource { get; set; }
}

但是,我无法访问这两个属性中的任何一个并通过 XAML 显示图像。

<ListView ItemsSource="{Binding MediaList}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="10">
                    <Image Source="{Binding ImageSource}" VerticalOptions="Fill"></Image>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

现在我很困惑,因为我能够通过 XAML 通过标签输出 string Image,但根本无法显示路径中的图像。

【问题讨论】:

  • 尝试绑定到图像路径字符串。路径是 url、完整文件路径、部分文件路径等吗?
  • 至少在代码中你没有名为MediaList的属性

标签: c# xaml xamarin xamarin.forms imagesource


【解决方案1】:

您可以像这样使用ImageSource.FromFile()ImageSource.FromUri()

在 Xaml 中

<Image  Source="{Binding  ImageSource}"  Aspect="AspectFit"  ></Image>

在代码中

public ObservableCollection<Item> MediaList { get; set; } = new ObservableCollection<Item>()
        {
            new Item
            {
                ImageSource = ImageSource.FromFile("xamarin.png")
            },
            new Item
            {
                ImageSource = ImageSource.FromUri(new Uri("https://i.stack.imgur.com/4mMod.png"))
            }
        };

结果

更新

取决于Microsoft-Local Images

图像文件可以添加到每个应用程序项目中,并从 Xamarin.Forms 共享代码中引用...

要在所有应用中使用单个图像,必须在每个平台上使用相同的文件名,并且它应该是有效的 Android 资源名称(即只允许使用小写字母、数字、下划线和句点)。

更多信息请看答案here

现在如果你想在不添加到每个平台的情况下显示图像,你应该使用Converter

例如:

  1. 在共享代码中创建一个名为ImagesFolder 的新文件夹,然后将图像添加到其中

  2. 在代码中,像这样创建一个名为 ByteArrayToImageSourceConverter 的新类

    public class ByteArrayToImageSourceConverter : IValueConverter 
    {
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {   
        byte[] bytes;
        var assembly = GetType().GetTypeInfo().Assembly; // using System.Reflection;
    
        var stream = assembly.GetManifestResourceStream((string)value); // value = "App1.ImagesFolder.ninja.png"
        using (var ms = new MemoryStream()) // using System.IO; 
        {
            stream.CopyToAsync(ms);
            bytes = ms.ToArray();
        }
        return ImageSource.FromStream(() => new MemoryStream(bytes));
      }
      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {
        return null;
      }
    }
    

    查看模型

    public ObservableCollection<Item> MediaList { get; set; } = new ObservableCollection<Item>()
    {
        new Item
        {
           Image  = "App1.ImagesFolder.ninja.png"
        }
    };
    
  3. 在 Xaml 中

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:App1"
         x:Class="App1.MainPage">
    
      <ContentPage.Resources>
        <ResourceDictionary>
           <local:ByteArrayToImageSourceConverter  x:Key="ByteArrayToImageSourceConverter" />
       </ResourceDictionary>
     </ContentPage.Resources>
    
     <ListView ItemsSource="{Binding MediaList}" >
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
               <Image Source="{Binding Image, Converter={StaticResource ByteArrayToImageSourceConverter}}" />
            </ViewCell>
          </DataTemplate>
       </ListView.ItemTemplate>
     </ListView>
    
    </ContentPage>
    

相关链接

ByteArrayToImageSourceConverter

Shared Resources

How to load binary images in Xamarin?

【讨论】:

  • 我想如果图像在磁盘上的某个地方(例如桌面)随机出现,但只有当它位于项目的子文件夹中时,它才会起作用?
  • @Bowser 我已经修改了我的答案
【解决方案2】:

ImageSource 类型更改为String

public class Item
{
    public string ImageSource { get; set; }
}

用法

List<Item> items = new List<Item>();
items.Add(new Item() { ImageSource = "*THE URL OF IMAGE*" });
ListView.ItemsSource = items;

【讨论】:

  • 正如您在上面看到的,我已经有一个字符串(文件路径),但是无论出于何种原因,使用Binding Image 时该字符串都不起作用。也就是说,不管我改不改成字符串,都是一样的(我已经试过了)。
  • 你试过这个代码List&lt;Item&gt; items = new List&lt;Item&gt;(); items.Add(new Item() { ImageSource = "*THE URL OF IMAGE*" }); ListView.ItemsSource = items;
  • 您可以通过@"File://"开头的路径来使用磁盘中的图像
  • 我同意艾哈迈德的回答。我在 vmodel 中有一个图像路径字符串属性,如下所示,它绑定到 XAML 中的图像: public string Text { get { return this.text; } 设置 { this.text = 值; this.OnPropertyChanged(nameof(Text)); } }
猜你喜欢
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
相关资源
最近更新 更多