5

I have a converter that allow me to convert between SelectedItems and a Generic List<MyType>

public class SelectedTiposDocsToList : BaseConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var Selecteditems = value as IList;
        List<MyType> MyTypeList = Selecteditems.Cast<MyType>().ToList();
        return MyTypeList;
    }

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

Now this is a common task for me and want to extend this class to allow a generic type is this something like this maybe ?

public class SelectedTiposDocsToList : BaseConverter, IValueConverter
{
    public object Convert<T>(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var Selecteditems = value as IList;
        List<T> MyTypeList = Selecteditems.Cast<T>().ToList();
        return MyTypeList;
    }

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

Is this Possible ? If Yes.. How to use thsi type of converter on XAML ?

Juan Pablo Gomez
  • 5,203
  • 11
  • 55
  • 101
  • I'm going to say no, since you wouldn't be implementing the interface anymore. An interesting question though! Could you pass the type on the parameter variable instead? – BradleyDotNET May 20 '14 at 00:04
  • Maybe. But really don't have much experience on this. And don't know how to pass more parameters to the converte just using XAML sintax. – Juan Pablo Gomez May 20 '14 at 00:07
  • I agree with Bradley. However, you could make the converter call a service that uses generics. Nothing prevents that. Pass the class in the converter's parameter... – Gayot Fow May 20 '14 at 00:07
  • @GayotFow. Maybe some sample to see how ? – Juan Pablo Gomez May 20 '14 at 00:09
  • @JuanPabloGomez, there's a wonderful answer from the legendary Skeet with 97 up votes on how to do this here http://stackoverflow.com/questions/325156/calling-generic-method-with-a-type-argument-known-only-at-execution-time – Gayot Fow May 20 '14 at 00:18

2 Answers2

4

No, this would not be a valid implementation of IValueConverter. However, you can pass a type on the parameter:

{Binding MyVariable, Converter={StaticResource SelectedTiposDocsToList}, ConverterParameter={x:Type local:MyType}}

Then you would use Select with the Convert.ChangeType method: MSDN

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var Selecteditems = value as IList;
    var MyTypeList = Selecteditems.Cast<object>().Select((i) => System.Convert.ChangeType(i, parameter as Type)).ToList();
    return MyTypeList;
}

Verified as compiling on VS 2013.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
1

This can be done with a bit of reflection: Type.MakeGenericType to get the type, Activator.CreateInstance to invoke the right constructor, and MethodInfo.MakeGenericMethod to give the parameter to Cast.

public Type ConvertType { get; set; }
public object Convert(object value, Type targetType, object parameter,
                      System.Globalization.CultureInfo culture)
{
    var type = typeof(List<>).MakeGenericType(ConvertType);
    var methodInfo = typeof(Enumerable).GetMethod("Cast");
    var genericMethod = methodInfo.MakeGenericMethod(ConvertType);
    var convertTypeList = Activator.CreateInstance(type,
                    genericMethod.Invoke(null, new[] { value }));
    return convertTypeList;
}

You can specify the type in XAML with x:Type.

<myns:SelectedTiposDocsToList x:Key="Conv" ConvertType="{x:Type myns:MyType}" />
Tim S.
  • 55,448
  • 7
  • 96
  • 122