【问题标题】:How can I implement binding for an Imbedded Image Resource?如何实现嵌入图像资源的绑定?
【发布时间】:2021-11-20 19:59:37
【问题描述】:
  1. 我正在尝试将 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 或事件,或者值和属性之间的类型不匹配。

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

【问题讨论】:

    标签: c# xaml xamarin.forms data-binding markup-extensions


    【解决方案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】:

      不需要编写标记扩展。

      1. 创建一个 ImageSource 属性并绑定到 xaml 中的该属性。
      2. 使用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 的图像。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        • 2011-08-13
        • 1970-01-01
        • 1970-01-01
        • 2013-12-05
        相关资源
        最近更新 更多