Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有可绑定属性的IMarkupExtension_C#_Xaml_Xamarin_Binding_Markup Extensions - Fatal编程技术网

C# 具有可绑定属性的IMarkupExtension

C# 具有可绑定属性的IMarkupExtension,c#,xaml,xamarin,binding,markup-extensions,C#,Xaml,Xamarin,Binding,Markup Extensions,我为ImageSource创建了一个IMarkupExtension,它从指定的字体中获取指定的符号,并以指定的颜色和高度显示它。大多数时候图标名是静态的,我直接写入XAML。但有时会有一些东西的列表,它们的属性决定了应该使用哪个图标。在这种情况下,图标名称必须是可绑定的 以下是myFontImageExtension的当前状态(或多或少): [ContentProperty(nameof(IconName))] public class FontImageExtension : IMarkup

我为
ImageSource
创建了一个
IMarkupExtension
,它从指定的字体中获取指定的符号,并以指定的颜色和高度显示它。大多数时候图标名是静态的,我直接写入XAML。但有时会有一些东西的列表,它们的属性决定了应该使用哪个图标。在这种情况下,图标名称必须是可绑定的

以下是my
FontImageExtension的当前状态(或多或少):

[ContentProperty(nameof(IconName))]
public class FontImageExtension : IMarkupExtension<ImageSource>
{
    private readonly IconFontService iconFontService;

    [TypeConverter(typeof(FontSizeConverter))]
    public double Size { get; set; } = 30d;

    public string IconName { get; set; }

    public Color Color { get; set; }

    public string FontFamily { get; set; }

    public FontImageExtension()
    {
        iconFontService = SomeKindOfContainer.Resolve<IconFontService>();
    }

    public ImageSource ProvideValue(IServiceProvider serviceProvider)
    {
        if (string.IsNullOrEmpty(IconName))
            return null;

        IconFont iconFont = iconFontService.GetIconFont();

        if (iconFont == null)
            return null;

        string glyphCode = iconFont.GetGlyphCode(IconName);

        if (string.IsNullOrEmpty(glyphCode))
            return null;

        FontImageSource fontImageSource = new FontImageSource()
        {
            FontFamily = iconFont.GetPlatformLocation(),
            Glyph = glyphCode,
            Color = this.Color,
            Size = this.Size,
        };

        return fontImageSource;
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return ProvideValue(serviceProvider);
    }
}
[ContentProperty(nameof(IconName))]
公共类FontImageExtension:IMarkupExtension
{
专用只读IContService IContService;
[TypeConverter(typeof(FontSizeConverter))]
公共双尺寸{get;set;}=30d;
公共字符串IconName{get;set;}
公共颜色{get;set;}
公共字符串{get;set;}
公共FontImageExtension()
{
icontservice=SomeKindOfContainer.Resolve();
}
公共ImageSource ProviderValue(IServiceProvider服务提供商)
{
if(string.IsNullOrEmpty(IconName))
返回null;
icont icont=icontservice.geticont();
如果(iconFont==null)
返回null;
字符串glyphCode=iconFont.GetGlyphCode(IconName);
if(string.IsNullOrEmpty(glyphCode))
返回null;
FontImageSource FontImageSource=新FontImageSource()
{
FontFamily=iconFont.GetPlatformLocation(),
字形=字形代码,
颜色=这个,
大小=这个。大小,
};
返回图像源;
}
对象IMarkupExtension.ProviderValue(IServiceProvider服务提供者)
{
返回ProvideValue(服务提供商);
}
}
大多数情况下,我在XAML中都是这样使用它的(它已经很好地工作了):


但对于动态用户界面(例如列表或其他),我需要如下所示:

<CollectionView ItemsSource={Binding SomeCollection}">
    <CollectionView.ItemTemplate>
        <StackLayout>
            <Image Source="{m:FontImage IconName={Binding ItemIcon}, Color=Black, Size=48}"/>
            <Label Text="{Binding ItemText}"/>
        </StackLayout>
    </CollectionView.ItemTemplate>
</CollectionView>
<Image Source="{Binding IconNameProperty, Converter={c:FontIconConverter Color=Black, Size=48}}"/>
<Image Source="{m:FontImage SomeIconsName, Color=Black, Size=48}"/>

您似乎无法将
IMarkupExtension
与可绑定属性一起使用。因为“绑定”只能在BindableObject的BindableProperty上设置。问题是MarkupExtension类不是从BindableObject派生的,这就是为什么无法在其属性上设置绑定。尽管您允许它实现BindableObject,它仍然无法工作

正在使用一种变通方法

例如:

class ImageSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var p = parameter.ToString().Split('|');
        string colorName = p[0];
        ColorTypeConverter colorTypeConverter = new ColorTypeConverter();
        Color color = (Color)colorTypeConverter.ConvertFromInvariantString(colorName);
        double fontSize = double.Parse(p[1]);

        //didn't test this here.
        IconFontService iconFontService = SomeKindOfContainer.Resolve<IconFontService();
        IconFont iconFont = iconFontService.GetIconFont();
        if (iconFont == null)
            return null;

        string glyphCode = iconFont.GetGlyphCode((string)value);
        if (string.IsNullOrEmpty(glyphCode))
            return null;

        FontImageSource fontImageSource = new FontImageSource()
        {
            FontFamily = iconFont.GetPlatformLocation(),
            Glyph = glyphCode,
            Color = color,
            Size = fontSize,
        };
        return fontImageSource;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
class ImageSourceConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
var p=parameter.ToString().Split(“|”);
字符串colorName=p[0];
ColorTypeConverter ColorTypeConverter=新的ColorTypeConverter();
Color Color=(Color)colorTypeConverter.ConvertFromInvariantString(colorName);
double-fontSize=double.Parse(p[1]);
//这里没有测试这个。

IconFontService IconFontService=SomeKindOfContainer.Resolve我通过创建一个转换器(如@Leo Zhu建议的)解决了这个问题,但是除了
IMarkupExtension
。因此我的扩展保持原样(添加了一个在转换器中使用的常量值),转换器的代码如下:

public class FontIconConverter : IValueConverter, IMarkupExtension
{
    private IServiceProvider serviceProvider;

    public Color Color { get; set; }

    [TypeConverter(typeof(FontSizeConverter))]
    public double Size { get; set; } = FontIconExtension.DefaultFontSize;

    public string FontFamily { get; set; }

    public FontIconConverter()
    {
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is string iconName))
            return null;

        var fontIcon = new FontIconExtension()
        {
            IconName = iconName,
            Color = Color,
            Size = Size,
            FontFamily = FontFamily,
        };

        return fontIcon.ProvideValue(serviceProvider);
    }

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

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
        return this;
    }
}
然后可以这样使用:

<CollectionView ItemsSource={Binding SomeCollection}">
    <CollectionView.ItemTemplate>
        <StackLayout>
            <Image Source="{m:FontImage IconName={Binding ItemIcon}, Color=Black, Size=48}"/>
            <Label Text="{Binding ItemText}"/>
        </StackLayout>
    </CollectionView.ItemTemplate>
</CollectionView>
<Image Source="{Binding IconNameProperty, Converter={c:FontIconConverter Color=Black, Size=48}}"/>
<Image Source="{m:FontImage SomeIconsName, Color=Black, Size=48}"/>

对于静态值,它保持如下状态:

<CollectionView ItemsSource={Binding SomeCollection}">
    <CollectionView.ItemTemplate>
        <StackLayout>
            <Image Source="{m:FontImage IconName={Binding ItemIcon}, Color=Black, Size=48}"/>
            <Label Text="{Binding ItemText}"/>
        </StackLayout>
    </CollectionView.ItemTemplate>
</CollectionView>
<Image Source="{Binding IconNameProperty, Converter={c:FontIconConverter Color=Black, Size=48}}"/>
<Image Source="{m:FontImage SomeIconsName, Color=Black, Size=48}"/>


让FontIconConverter直接实现IMarkupExtension是个好主意。如果我的答案对您有帮助,您可以将其标记为接受答案,或者您可以标记自己。它可能会帮助其他人。