AndreaGobs
AndreaGobs

Reputation: 386

Issue with Xamarin Forms 4 using ItemTemplate binding in CollectionView

To customize the appearance of an item in the CollectionView, I'm using a DataTemplateSelector, but unlike what happens in the ListView data binding doesn't seem to work for ItemTemplate in the CollectionView.

I have already tested my solution with a ListView in place of the CollectionView and it works. Everything works fine also if I replace the resource ItemTemplate binding with the inline ItemTemplate.

I'm trying to customize different objects which inherit from ISensor. It looks like

public interface ISensor
{
    string Name { get; set; }
    // ...
}

This is the view model:

public class TestViewModel : MvxNavigationViewModel
{
    private static ObservableCollection<ISensor> _SensorList;

    public TestViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigation)
        : base(logProvider, navigation)
    {
        _SensorList = new ObservableCollection<ISensor> { new Sensor("Thermostat"), null };
    }

    public ObservableCollection<ISensor> SensorsSource { get => _SensorList; }
}

And this is the page containing the CollectionView:

<ContentView>
    <StackLayout>
        <CollectionView ItemsSource="{Binding SensorsSource}" ItemTemplate="{StaticResource SensorsTemplate}" Margin="10">
            <CollectionView.ItemsLayout>
                <GridItemsLayout Orientation="Vertical" Span="2"/>
            </CollectionView.ItemsLayout>

            <CollectionView.EmptyView>
                <StackLayout>
                    <Label Text="Add a new sensor"/>
                </StackLayout>
            </CollectionView.EmptyView>
        </CollectionView>

    </StackLayout>
</ContentView>

The DataTemplateSelector:

public class SensorSelector : DataTemplateSelector
{
    public DataTemplate EmptyTemplate { get; set; }
    public DataTemplate SensorTemplate { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        if (item is Sensor)
            return SensorTemplate;
        return EmptyTemplate;
    }
}

The DataTemplate present in the App.xaml file:

<DataTemplate x:Key="EmptyDataTemplate">
    <ViewCell>
        <StackLayout BackgroundColor="Yellow">
            <Label Text="EMPTY"/>
        </StackLayout>
    </ViewCell>
</DataTemplate>
<DataTemplate x:Key="SensorDataTemplate">
    <ViewCell>
        <StackLayout BackgroundColor="Red">
            <Label Text="{Binding Name}"/>
        </StackLayout>
    </ViewCell>
</DataTemplate>
<Selectors:SensorSelector x:Key="SensorsTemplate" 
                          EmptyTemplate="{StaticResource EmptyDataTemplate}"
                          SensorTemplate="{StaticResource SensorDataTemplate}"/>

Every time I enter in the TestViewModel the app crash. Is it a binding bug or am I doing something wrong?

Upvotes: 0

Views: 1317

Answers (1)

DavidS
DavidS

Reputation: 2934

With ListView, the child of the DataTemplate used as the ItemTemplate must be a ViewCell (or derive from it). With CollectionView, you cannot have the ViewCell in place. In other words, you can't have a DataTemplate that works with both ListView and CollectionView simultaneously. Removing the ViewCell layer in your DataTemplates should fix the crash when using with CollectionView:

<DataTemplate x:Key="EmptyDataTemplate">
    <StackLayout BackgroundColor="Yellow">
        <Label Text="EMPTY"/>
    </StackLayout>
</DataTemplate>

And the equivalent change for the SensorDataTemplate.

Upvotes: 2

Related Questions