unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.97k stars 730 forks source link

When using a DataTemplateSelector with FlipView and Pivot, data templates are not being applied to the items on Android #6030

Closed kotturtech closed 2 years ago

kotturtech commented 3 years ago

Current behavior

In the following controls: FlipView, Pivot: When setting the ItemTemplateSelector property (Using custom template selector), data templates are still not being applied on items. Instead, a string with the type name of the item (ViewModel) appears. This issue reproduces for me on Android platform only, whereas on UWP platform everything works fine

This issue seems to be akin to the following previous issue: https://github.com/unoplatform/uno/issues/491

Expected behavior

Data tempates generated by the Template Selector should be applied to items according to the logic of the specified DataTemplateSelector

How to reproduce it (as minimally and precisely as possible)

The following example demonstrates the issue. I have used a FlipView in my example, however the issue similarly reproduces with the Pivot control as well.

Code:

using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;

namespace TemplateSelectorIssue
{
    [ContentProperty(Name="Mappings")]
    class ViewSelector : DataTemplateSelector
    {
        public VMMappingsDictionary Mappings { get; set; }

        protected override DataTemplate SelectTemplateCore(object item)
        {
            var t = item.GetType().Name;
            if (Mappings.TryGetValue(t, out var dt))
                return dt;
            return base.SelectTemplateCore(item);
        }

        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)=> SelectTemplateCore(item);
    }

    class VMMappingsDictionary : Dictionary<string,DataTemplate>
    {

    }

    class Vm1
    {
        public string Text => "Beast";
    }

    class Vm2
    {
        public int Num => 666;
    }

    class MainVM
    {
        public object[] Items => new object[]
        {
            new Vm1(), new Vm2()
        };
    }
}

XAML:

<Page
    x:Class="TemplateSelectorIssue.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TemplateSelectorIssue"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.DataContext>
        <local:MainVM/>
    </Page.DataContext>

    <FlipView ItemsSource="{Binding Items}">
        <FlipView.ItemTemplateSelector>
            <local:ViewSelector>
                <local:VMMappingsDictionary>
                    <DataTemplate x:DataType="local:Vm1" x:Key="Vm1">
                        <TextBlock Text="{Binding Text}"/>
                    </DataTemplate>
                    <DataTemplate x:DataType="local:Vm2" x:Key="Vm2">
                        <TextBlock Text="{Binding Num}"/>
                    </DataTemplate>
                </local:VMMappingsDictionary>
            </local:ViewSelector>
        </FlipView.ItemTemplateSelector>
    </FlipView>
</Page>

Workaround

Since this issue is akin to issue 491, I will try a similar workaround in my case as well. Currently can't confirm that it works though

Environment

Nuget Package:

Nuget Package Version(s):

Affected platform(s):

IDE:

Relevant plugins:

Anything else we need to know?

kotturtech commented 3 years ago

After some search for a workaround, I have come up with the following solution:

To make the TemplateSelector work on Android, I've created the TemplateSelector as a static resource, and assigned it in the style of the FlipViewItem, as follows (Omitting some irrelevant specifics):


   <xamarin:FlipView ItemsSource="{Binding Pages}" SelectedItem="{Binding SelectedPage,Mode=TwoWay}">
        <xamarin:FlipView.Resources>
            <infraUI:ViewSelector x:Key="ViewSelector">
                <!-- This is my TemplateSelector-->
            </infraUI:ViewSelector>
            <Style TargetType="FlipViewItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="FlipViewItem">
                            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplateSelector="{StaticResource ViewSelector}">
                            </ContentPresenter>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </xamarin:FlipView.Resources>
    </xamarin:FlipView>

However, this approach won't work properly on UWP. Therefore, I have resorted to platform-specific xaml and implemented the view separately for UWP and for other platforms. My solution for UWP is simply assigning the TemplateSelector to FlipView.ItemTemplateSelector property.

MaksimNikonovOrioninc commented 3 years ago

I have same problem but in WASM project and in relation to ListView

Guidemarcus commented 2 years ago

I have this issue too. I tried with uno.ui 3.8, 3.11 and 4.4. The version 3.X are working fine, version 4.4 seems to be working fine, but I saw #8637. The only way I was able to reproduce this was to add Uno.Material to my project