在 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
只需返回图像的路径。 SomeImage
和 OtherProperty
是您的视图模型类的成员,OtherProperty
只是您的图像名称的基础(因为如果您提前知道全名,则不需要这个问题)。
【讨论】:
我发现您实际上需要在 ViewModel 中返回 ImageSource 而不是字符串: public ImageSource SomeImage => ImageSource.FromResource($"(ProjectName).Images.(ImageName)");它还显示(至少在 android 上)文件名中的连字符不能使用 ^^ 这完全不正确 - 你绝对可以从 ViewModel 返回一个字符串。我无法评论文件名中的连字符,因为我们没有。事实上,通过我正在解释的方法尝试你的建议,我相当肯定根本不起作用:)。 那肯定有一些我没有看到的细微差别。字符串对我不起作用,但返回图像源可以:) 我假设你没有像我上面的<FileImageSource>
那样设置它
这应该是公认的答案,它就像一个魅力!【参考方案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 会将其转换为平台的正确格式。
【讨论】:
如何更改图片来源?海滩不会因与您的示例绑定而改变 你可以像这样声明你的图像:<Image> <Image.Source> <FileImageSource File="Binding Img" /> </Image.Source> </Image>
,然后提供一个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 内容绑定
如何使用 xamarin.forms-shell 在 XAML 中动态绑定类型为 <ShellContent> 的 Tab.Items 列表