-1

How to define array values in a single line in XAML?

 <Image Source="{ Binding ImageUrl }" 
        Opacity="{Binding Selected, 
             Converter={StaticResource BoolToDouble}, 
             ConverterParameter={ Array Type={ Type system:Double }, Items=??? } }" >

Items are unique for this field so it seems bad to put it in ResouceDictionary or BindingModel

I know I can use it like this, but it seems to be huge overkill for something like this

    <Image Source="{ Binding ImageUrl }">
          <Image.Opacity>
            <Binding Path="Selected" Converter="{StaticResource BoolToDouble }">
                <Binding.ConverterParameter>
                    <x:Array Type="{Type system:Double}">
                        <x:Double>0.65</x:Double>
                        <x:Double>0.95</x:Double>
                    </x:Array>
                </Binding.ConverterParameter>
            </Binding>
        </Image.Opacity>
    </Image>
EOG
  • 1,677
  • 2
  • 22
  • 36
  • Xaml is verbose. I recall there were alternatives, something what looks like a json, maybe someone can provide a name? As for a request, you can make [custom xaml extention](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/markup-extensions/creating) to specify array in different way, see e.g. [this](https://stackoverflow.com/q/8302408/1997232). – Sinatr Mar 05 '21 at 15:24
  • There is a phenomenon going on that any questions in XAML or even WPF are voted down. stack moderators really need to look into this. – zar Mar 05 '21 at 15:29
  • Since you are passing parameter, maybe it will be better to pick it from viewmodel so you don't have to write those lines here. Other than that, this is right way and easy to read but xaml is verbose which comes from xml itself. – zar Mar 05 '21 at 20:06

2 Answers2

0

pass parameter as string

<Image Source= "{Binding ImageUrl}" 
       Opacity="{Binding Selected, 
                         Converter={StaticResource BoolToDouble}, 
                         ConverterParameter='0.65 0.95'}" >

parse it in converter:

double[] array = parameter.ToString()
                          .Split(' ')
                          .Select(x => double.Parse(x))
                          .ToArray();

(there are more complex formats in WPF, e.g. Geometry.Data. It is handled by TypeConverter, not ValueConverter but still)

ASh
  • 34,632
  • 9
  • 60
  • 82
  • It adds additional overhead to parse it every time bounded value changes. It's more workaround than a real solution – EOG Mar 05 '21 at 15:30
  • then stick with something that works. real solution, no overhead, no development costs. "I know I can use it like this, but it seems to be huge overkill " - very subjective. xml is verbose, but people use it. write it once and forget – ASh Mar 05 '21 at 15:32
0

I ended up createing an extensions for just that, I am posting it here for everyone to use if needed.

using System;
using System.Collections;

namespace Xamarin.Forms.Xaml
{
    [AcceptEmptyServiceProvider]
    public class ConvertibleValueExtension : IMarkupExtension
    {
        public Type Type { get; set; }
        public string Value { get; set; }
        public bool IsArray { get; set; }
        public IFormatProvider FormatProvider { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Type is null) throw new InvalidOperationException("Type argument mandatory for ConvertibleValues extension");

            if (string.IsNullOrWhiteSpace(Value)) return default;

            if (typeof(IConvertible).IsAssignableFrom(Type))
            {
                if (IsArray)
                {
                    var sVals = Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    //creates typed array instead of object[] as linq query does
                    var result = Array.CreateInstance(Type, sVals.Length); 

                    for (int i = 0; i < sVals.Length; i++)
                    {
                        ((IList) result)[i] = Convert.ChangeType(sVals[i], Type, FormatProvider);
                    }

                    return result;
                }

                return Convert.ChangeType(Value, Type, FormatProvider);
            }

            return default;
        }
    }
}

example use

 <Image Source="{ Binding ImageUrl }" 
        Opacity="{Binding Selected, 
                Converter={StaticResource BoolToDouble}, 
                ConverterParameter={ xaml:ConvertibleValue Type={ Type system:Double }, Value='0.5 0.6', IsArray=True } }" />

I should be used only for uniques values or prototyping

EOG
  • 1,677
  • 2
  • 22
  • 36