xamarin 如何创建具有可绑定属性的标记扩展?

zqry0prt  于 8个月前  发布在  其他
关注(0)|答案(1)|浏览(77)

我希望有一个名为RgbColorExtension的标记扩展,其中R属性是可绑定的,以便我使用滑块调整其值。
以下尝试不起作用。更改滑块不会影响R属性。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Sandbox.MainPage"
             xmlns:local="clr-namespace:Sandbox"
             >
    <VerticalStackLayout>
        <Slider x:Name="slider" Maximum="1"/>
        <Label Text="{Binding Value,Source={x:Reference slider}}"/>
        <BoxView HeightRequest="200" WidthRequest="200">
            <BoxView.Color>
                <local:RgbColor R="{Binding Value,Source={x:Reference slider}}" G="0" B="0" A="0.5"/>
            </BoxView.Color>
        </BoxView>
        <BoxView 
            HeightRequest="200" 
            WidthRequest="200"
            Color="{local:RgbColor R={Binding Value,Source={x:Reference slider}},G=0.5,B=0.5,A=.5}"
            />
    </VerticalStackLayout>

</ContentPage>
namespace Sandbox;

public class RgbColorExtension : BindableObject, IMarkupExtension<Color>
{

    public static readonly BindableProperty RProperty =
        BindableProperty.Create(nameof(R), typeof(float), typeof(RgbColorExtension), 0.5f);

    public float R
    {
        get => (float)GetValue(RProperty);
        set => SetValue(RProperty, value);
    }

    public float G { get; set; }
    public float B { get; set; }
    public float A { get; set; }

    public Color ProvideValue(IServiceProvider serviceProvider)
    {
        return Color.FromRgba(R, G, B, A);
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<Color>).ProvideValue(serviceProvider);
    }
}

我错过了什么?

pzfprimi

pzfprimi1#

因为有4个参数,所以可以让IMarkupExtension实现(1)BindableObject(已经实现了),(2)MultiBinding,以及(3)IMultiValueConverter。4个float值可以参与MultiBindingIMultiValueConverter将这4个float值转换为Color值。
下面是一个工作实现:

[ContentProperty("R")]
public class RgbColorExtension : BindableObject, IMarkupExtension<BindingBase>, IMultiValueConverter
{
    public static readonly BindableProperty RProperty
        = BindableProperty.Create(nameof(R), typeof(float), typeof(RgbColorExtension));

    public static readonly BindableProperty GProperty
        = BindableProperty.Create(nameof(G), typeof(float), typeof(RgbColorExtension));

    public static readonly BindableProperty BProperty
        = BindableProperty.Create(nameof(B), typeof(float), typeof(RgbColorExtension));

    public static readonly BindableProperty AProperty
        = BindableProperty.Create(nameof(A), typeof(float), typeof(RgbColorExtension));

    public float R
    {
        get { return (float)GetValue(RProperty); }
        set { SetValue(RProperty, value); }
    }

    public float G
    {
        get { return (float)GetValue(GProperty); }
        set { SetValue(GProperty, value); }
    }

    public float B
    {
        get { return (float)GetValue(BProperty); }
        set { SetValue(BProperty, value); }
    }

    public float A
    {
        get { return (float)GetValue(AProperty); }
        set { SetValue(AProperty, value); }
    }

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
    }

    BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
    {
        return new MultiBinding()
        {
            Converter = this,
            Mode = BindingMode.OneWay,
            Bindings = new Collection<BindingBase>
            {
                new Binding(nameof(R), BindingMode.OneWay, null, null, null, this),
                new Binding(nameof(G), BindingMode.OneWay, null, null, null, this),
                new Binding(nameof(B), BindingMode.OneWay, null, null, null, this),
                new Binding(nameof(A), BindingMode.OneWay, null, null, null, this)
            }
        };
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        float R = (float)values[0];
        float G = (float)values[1];
        float B = (float)values[2];
        float A = (float)values[3];
        return Color.FromRgba(R, G, B, A);
    }

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

相关问题