【问题标题】:Binding image source dynamically on xamarin forms在 xamarin 表单上动态绑定图像源
【发布时间】: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 这行不通。您应该将它们放置在每个项目各自的资源位置

标签: c# image xamarin binding xamarin.forms


【解决方案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' 不加载图片
  • 我在我的所有项目中都使用这个代码,所以我可以保证如果使用得当,它会按照它说的去做。当然,它可能会在我没想到的情况下失败。您能告诉我您正在搜索的文件名,以及它在您的项目中的位置吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 2018-06-25
  • 2017-08-15
  • 2011-05-11
  • 2023-04-04
相关资源
最近更新 更多