microsoft / XamlBehaviors

This is the official home for UWP XAML Behaviors on GitHub.
MIT License
697 stars 112 forks source link

TypeConverterHelper does not support types in other assemblies #158

Closed rdadkins closed 4 years ago

rdadkins commented 5 years ago

Take the following example:

<DataGrid>
  <Interactivity:Interaction.Behaviors>
    <Interactions:EventTriggerBehavior EventName="SelectionChanged">
      <Interactions:ChangePropertyAction
        TargetObject="{x:Bind ViewModel}"
        PropertyName="SomeCollection"
        Value="{x:Bind DataGrid.SelectedItems, Converter={Custom collection converter},
          ConverterParameter='Fully qualified collection generic type'}" />
    </Interactions:EventTriggerBehavior>
  </Interactivity:Interaction.Behaviors>
</DataGrid>

Custom collection converter: an IValueCoverter that attempts to convert an IList to an IList<T> where T is the type specified by the converter parameter.

The issue: TypeConverterHelper does not support types found in other assemblies (the private GetType(string) is the cause).

If the destination type is IList<MyType>, the name passed to TypeConverterHelper.GetType would look like:

System.Collections.Generic.IList`1[[Custom.Model.MyType, Custom.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

GetType(string) implementation of LastIndexOf(".") does not account for the assembly qualified name being included and thus resulting in an invalid type being parsed.

rdadkins commented 5 years ago

Put more simply, TypeConverterHelper.Convert is trying to convert from IList<object> to IList<MyType> but MyType has assembly information attached to it. Thus, both the scope and type is incorrect due to a . found in the assembly version.

rdadkins commented 5 years ago

This only seems to be the case for generic collections. See here

pedrolamas commented 4 years ago

If you look at the source code for TypeConverterHelper you will see it actually uses XamlReader to perform the type conversion and that is via a XAML bit of code.

Unfortunately, generics are only supported in XAML 2009 but UWP is based on XAML 2006 so there is no way for us to use it.

The easy way to fix this problem is to just create your own type based on List<T> and use it on the property types, like so:

public class MyCollection: List<MyType>
{
    public MyCollection() : base()
    {
    }

    public MyCollection(IEnumerable<MyType> collection) : base(collection)
    {
    }

    public MyCollection(int capacity) : base(capacity)
    {
    }
}

Closing this for now, feel free to open if you have difficulties applying this solution.