在 xamarin 表单上动态绑定图像源

Posted

技术标签:

【中文标题】在 xamarin 表单上动态绑定图像源【英文标题】:Binding image source dynamically on xamarin forms 【发布时间】:2017-09-06 17:23:54 【问题描述】:

我的问题是,我可以将字符串图像绑定到图像源吗?我有多个图像,图像会根据条件改变。所以:

Xamarin 表单上的 Xaml:

<Image Source="Binding someImage" Aspect="Fill" Grid.Row="2"></Image>

C#代码隐藏

   public String someImage;
    public String SomeImage
    
        set
        
            if (someImage != value)
            
                someImage = value;                                        
            
        
        get
        
            return someImage;
        
    

初始化组件部分:

if(true)
            
                someImage = "backgroundListViewGren.png";
            
            else
            
                someImage = "backgroundListViewRed.png";
            

图片位于可移植项目的“Images”文件夹中

但这不起作用,也许我错了,但我不明白。 有什么解决办法吗?

我尝试过使用 ImageSource 而不是字符串,但也不行。

【问题讨论】:

您的资源文件夹中有这样的图像吗?这些图片在哪里? 图像在便携式项目的“Images”文件夹中 你使用 INotifyPropertyChanged 吗?你应该设置 SomeImage = "xxx.png",而不是 someImage... 不,我不使用 INotifyPropertyChanged,会尝试 the image is in "Images" folder on portable project 这行不通。您应该将它们放置在每个项目各自的资源位置 【参考方案1】:

我将在此处发布此答案,因为它是我一直在寻找的答案,而且我怀疑大多数其他人都是(Google 目前将您引导至此处,这目前不是很有帮助)。

如何使用 XAML 绑定图像:

XAML:

<Image>
    <Image.Source>
        <FileImageSource File="Binding SomeImage" />
    </Image.Source>
</Image>

然后在 ViewModel 中,C#:

public string SomeImage

    get  return string.Format("prefix-0-suffix.png", OtherProperty); 

您可以使用更新、更好但本质上等效的 c# 来代替上面的:

public string SomeImage => $"prefix-OtherProperty-suffix.png";

这当然是最简单的设置方法,IMO :)。

编辑:不言而喻,但图像显然应该在每个平台的项目的Resources 文件夹中。

EDIT2,很久以后:如果不明显,“前缀”、“后缀”只是随机字符串,SomeImage 只需返回图像的路径。 SomeImageOtherProperty 是您的视图模型类的成员,OtherProperty 只是您的图像名称的基础(因为如果您提前知道全名,则不需要这个问题)。

【讨论】:

我发现您实际上需要在 ViewModel 中返​​回 ImageSource 而不是字符串: public ImageSource SomeImage => ImageSource.FromResource($"(ProjectName).Images.(ImageName)");它还显示(至少在 android 上)文件名中的连字符不能使用 ^^ 这完全不正确 - 你绝对可以从 ViewModel 返回一个字符串。我无法评论文件名中的连字符,因为我们没有。事实上,通过我正在解释的方法尝试你的建议,我相当肯定根本不起作用:)。 那肯定有一些我没有看到的细微差别。字符串对我不起作用,但返回图像源可以:) 我假设你没有像我上面的&lt;FileImageSource&gt;那样设置它 这应该是公认的答案,它就像一个魅力!【参考方案2】:

你说:

图像位于可移植项目的“Images”文件夹中

每个平台都有不同的资源和图像方法。 Xamarin 在每个平台上都会处理这个问题,例如 Xamarin.ios 具有嵌入式资源,而 Xamarin.Android 将 Android 资源用于图像。

您应该将图像放置在每个项目中,以便 Xamarin.Forms 知道在每个平台中的何处查找它们。

更多信息请查看this。

【讨论】:

也在各自的项目中 虽然我会推荐这个,但这不是绝对必要的【参考方案3】:

要使用来自 PCL 的图像,请查看 Xamarin documentation 中的此部分。

您应该确保将每个图像的Build action 设置为Embedded Resource

然后,如果您想在 XAML 中使用它们,请指定一个 MarkupExtension

[ContentProperty ("Source")]
public class ImageResourceExtension : IMarkupExtension

  public string Source  get; set; 

  public object ProvideValue (IServiceProvider serviceProvider)
  
    if (Source == null)
    
      return null;
    
    // Do your translation lookup here, using whatever method you require
    var imageSource = ImageSource.FromResource(Source);

    return imageSource;
  

然后您应该能够像这样使用您的图像。

<?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:WorkingWithImages;assembly=WorkingWithImages"
    x:Class="WorkingWithImages.EmbeddedImagesXaml">
  <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
    <!-- use a custom Markup Extension -->
    <Image Source="local:ImageResource WorkingWithImages.beach.jpg" />
  </StackLayout>
</ContentPage>

就像在 cmets 中提到的那样,如果您想让它开箱即用,请将它们放在您各自平台项目的 Resources 文件夹中。这样,您还可以利用现有的自动调整大小机制。要了解有关此方法的更多信息,请参阅page。

通过在正确的文件夹中使用正确的命名约定添加它们,您可以简单地引用文件名,Xamarin.Forms 会将其转换为平台的正确格式。

【讨论】:

如何更改图片来源?海滩不会因与您的示例绑定而改变 你可以像这样声明你的图像:&lt;Image&gt; &lt;Image.Source&gt; &lt;FileImageSource File="Binding Img" /&gt; &lt;/Image.Source&gt; &lt;/Image&gt;,然后提供一个ImageSource作为这样的绑定:public ImageSource Image get return ImageSource.FromResource(string.Format("Touchretail.Trims.Mobile.Images.0", IconSource)); 使用 .Net Std 项目时我需要使用: var assembly = Assembly.GetExecutingAssembly(); var imageSource = ImageSource.FromResource(Source, assembly);【参考方案4】:

我认为你可以做得更简单一些。这是我的工作。 将图像放在每个平台上的适当位置,例如。 Android 上的资源/可绘制对象

在您的 Xaml 中:

<Image Source="Binding someImage" Aspect="Fill" Grid.Row="2"></Image>

在您的视图模型中:

private string _someImage = "icon_eye_hidden";
    public string someImage
    

        get => this._someImage;
        set
        

            if (this._someImage == value) return;

            this._someImage = value;
            this.RaisePropertyChanged(() => this.someImage);
        
    

然后只需将 someImage 设置为图像的名称(不带扩展名),它应该会更新。

【讨论】:

这个不行,图片来源是网址! @user1034912 我保证它在当时有效,但我已经好几年没看过 Xam Forms 了。似乎是某种 Xamarin 在幕后绑定魔法。【参考方案5】:

我认为这不是最快的事情,但我找到了一种方法,在共享项目中只包含一次图像资源。

这还有一个优点,即文件在项目中的位置无关紧要,这对我有好处,因为我倾向于相当频繁地移动内容。

这是一个名为EmbeddedSourceror 的类。它基本上只是根据需要查找并返回资源:

public class EmbeddedSourceror

    //NOTE: if there are resources *anywhere* with identical names, this will only return the *first* one it finds, so don't duplicate names
    public static Xamarin.Forms.ImageSource SourceFor(string filenameWithExtension)
           
        var resources = typeof(EmbeddedSourceror).GetTypeInfo().Assembly.GetManifestResourceNames();

        var resourceName = resources.First(r => r.EndsWith(filenameWithExtension, StringComparison.OrdinalIgnoreCase));

        return Xamarin.Forms.ImageSource.FromResource(resourceName);
    
 

用法:

假设在 XAML 中定义为 centerImageElement 的图像元素:

centerImageElement.Source = EmbeddedSourceror.SourceFor("centerimage.png");

...您可以在运行时动态分配它。

【讨论】:

'ImageSource.FromResource' 不加载图片 我在我的所有项目中都使用这个代码,所以我可以保证如果使用得当,它会按照它说的去做。当然,它可能会在我没想到的情况下失败。您能告诉我您正在搜索的文件名,以及它在您的项目中的位置吗?

以上是关于在 xamarin 表单上动态绑定图像源的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 形成 MVVM Stacklayout 内容绑定

将数据集动态绑定到 RDLC 报告

如何使用 xamarin.forms-shell 在 XAML 中动态绑定类型为 <ShellContent> 的 Tab.Items 列表

动态填充后在另一个(未绑定的)表单中显示表单

Xamarin 将 ListView 项动态更新到 GUI

将图像添加到树视图控件 xamarin 表单中