如何实现嵌入图像资源的绑定?

Posted

技术标签:

【中文标题】如何实现嵌入图像资源的绑定?【英文标题】:How can I implement binding for an Imbedded Image Resource? 【发布时间】:2021-11-20 19:59:37 【问题描述】:
    我正在尝试将 ImageButton Source 连接到我的 MainPage 中的可变字符串属性。我不确定它是否是正确的方法。但是,我正在尝试找到一种使用绑定表达式将两者绑定在一起的方法。
namespace MyNameSpace

    public partial class MainPage : ContentPage, INotifyPropertyChanged
    

        public new  event PropertyChangedEventHandler PropertyChanged;
        public String One => "MyNameSpace.Images.Blue.jpg";

        public MainPage()
        

            InitializeComponent();

        
        protected override void OnPropertyChanged ([CallerMemberName] string name = null)
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
         
   

这是我创建的 MarkUpExtension,用于在使用嵌入式图像资源时将字符串作为资源提供。

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace MyNameSpace

    [ContentProperty("ResourceId")]
    public class EmbeddedImage : IMarkupExtension
    
        public string ResourceId  get; set;
        public object ProvideValue(IServiceProvider serviceProvider)
        
            if (String.IsNullOrWhiteSpace(ResourceId))
                return null;
            return ImageSource.FromResource(ResourceId);
        
    

这就是我试图在 xaml 中将字符串绑定在一起的方式...

<?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:MyNameSpace"
             x:Class="MyNameSpace.MainPage"
             x:Name = "Main">

    <StackLayout
        BindingContext="x:Reference Name=Main ">
        
       <Image
           
           Source="local:EmbeddedImage ResourceId = Binding One">
          
       </Image>    
       
    </StackLayout>

</ContentPage>

显然它不起作用...我收到错误:

MainPage.xaml(13, 12):[XFC0009] 找不到“ResourceId”的属性、BindableProperty 或事件,或者值和属性之间的类型不匹配。

也许这不是这样做的方法...有不同的方法吗?

【问题讨论】:

【参考方案1】:

您有一个可以更改的字符串,该字符串表示嵌入的资源(图像)

我的建议是使用Value Converters

首先,您必须修改字符串属性以在值发生变化时通知 UI

private string _one;
public string One

get=>_one; 
set_one=value; NotifyPropertyChanged();

然后您必须为转换器创建一个新类,这里将使用您的代码将字符串转换为 ImageSource

public class converter : IValueConverter
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        
            string ResourceId=value.ToString(); 
            if (String.IsNullOrWhiteSpace(ResourceId))
                return null;
            return ImageSource.FromResource(ResourceId);
        

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        
            throw new NotImplementedException();
        
    

然后,就像任何其他转换器一样,将其添加到App.xaml 中的应用程序资源中。这将根据您的名称类和命名空间而有所不同

        <converters:converter x:Key="myConverter"/>

最后是图片的代码

<Image Source="Binding One, Converter=StaticResource myConverter"/>

另外,如果您的应用程序不断增长,请考虑将 ViewModel 分离到另一个类

【讨论】:

【参考方案2】:

不需要编写标记扩展。

    创建一个 ImageSource 属性并绑定到 xaml 中的该属性。 使用ImageSource.FromStream方法设置属性(并传递嵌入的图像流)。

看看下面的例子。

代码隐藏

using System;
using System.IO;
using System.Reflection;

using Xamarin.Forms;

namespace App5

    public partial class MainPage
    
        public MainPage()
        
            InitializeComponent();
            SetImage();
        

        private int Num = 1;
        private static readonly Assembly Assembly = typeof(MainPage).Assembly;

        private ImageSource _Source;
        public ImageSource Source
        
            get => _Source;
            set
            
                _Source = value;
                OnPropertyChanged();
            
        

        private void SetImage()
        
            Source = ImageSource.FromStream(() => GetResourceStream($"Num.png"));
        

        private void bChange_OnClicked(object sender, EventArgs e)
        
            Num = Num == 1 ? 2 : 1;
            SetImage();
        

        private static Stream GetResourceStream(string filename)
            => Assembly.GetManifestResourceStream($"App5.filename");
    

XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="App5.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="This">

    <StackLayout>
        <Button Text="Change" Clicked="bChange_OnClicked" />
        <Image x:Name="img" Source="Binding Source,Source=x:Reference This" />
    </StackLayout>
</ContentPage>

为了使示例工作,您需要将项目默认命名空间设置为App5,并在根文件夹中嵌入两个文件名为1.png2.png 的图像。

【讨论】:

以上是关于如何实现嵌入图像资源的绑定?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现 ImageButtons 的绑定,以便仅在加载图像后显示图像?

如何将嵌入式图像与后面 C# 代码中的字符串指定的变量 ImageSource 绑定?

如何将资源嵌入到单个可执行文件中?

如何从 CSS 中引用嵌入的图像?

如何将占位符图像添加到嵌入的 Vimeo 和 Youtube 视频中?

如何使用 VLC 和 python 绑定播放图像幻灯片?