如果我使用 DataTemplateSelector,在哪里设置自定义单元格与客户渲染器的绑定?

Where to set bindings for a custom cell with customer renderer if I am using a DataTemplateSelector?

我有一个 DataTemplateSelector 可以在两个不同的单元格之间进行选择。在 Android,此模板选取定义为 Android xml 文件的单元格。我可以确认模板选择器正在工作,因为我显示了两个不同的色圈,而且颜色是正确的。但是我的数据没有被绑定,我不确定为什么。我想我没有在某处设置绑定,但我不确定 where/how 这样做。

这是我的页面,其中包含带有 DataTemplateSelector 的 ListView。我在这里设置了 ItemsSource,但我从未为列表项的不同部分设置绑定。这就是我不知道该怎么做的地方。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Pages.Routines.TopLevelRoutinesPage"
             xmlns:statics="clr-namespace:MyApp.Statics;assembly=MyApp"
             xmlns:controls="clr-namespace:MyApp.Controls;assembly=MyApp">
  <ContentPage.Resources>
    <ResourceDictionary>
      <controls:RoutinesDataTemplateSelector x:Key="RoutinesDataTemplateSelector"></controls:RoutinesDataTemplateSelector>
    </ResourceDictionary>
  </ContentPage.Resources>
  <ContentPage.Content>
    <StackLayout VerticalOptions="FillAndExpand"
                 HorizontalOptions="FillAndExpand"
                 Orientation="Vertical"
                 Spacing="0">
      <ListView ItemsSource="{Binding SelectedRoutineTree}"
                ItemTemplate="{StaticResource RoutinesDataTemplateSelector}"
                x:Name="RoutinesView"
                ItemSelected="RoutineClicked"
                Margin ="0, 8, 0, 0">
      </ListView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

隐藏代码:

using MyApp.ViewModels;
using MyCloudContracts.DTOs;
using System;
using System.Linq;
using Xamarin.Forms;

namespace MyApp.Pages.Routines
{
    public partial class TopLevelRoutinesPage : ContentPage
    {
        private TopLevelRoutinesViewModel _viewModel;
        private string _projCompName;

        public TopLevelRoutinesPage(Guid docId, bool fromCompany, string projCompName)
        {
            InitializeComponent();
            _projCompName = projCompName;
            Title = _projCompName;
            _viewModel = new TopLevelRoutinesViewModel(docId, fromCompany);
            BindingContext = _viewModel;

            if (Device.OS == TargetPlatform.Android)
                RoutinesView.SeparatorVisibility = SeparatorVisibility.None;
        }

        private async void RoutineClicked(object sender, SelectedItemChangedEventArgs e)
        {
            //since this is also called when an item is deselected, return if set to null
            if (e.SelectedItem == null)
                return;

            var selectedRoutine = (PublishedDocumentFragmentDTO)e.SelectedItem;
            var fragId = selectedRoutine.FragmentId;
            var title = selectedRoutine.Title;
            var blobIdStr = selectedRoutine.BlobId;
            var blobId = new Guid(blobIdStr);

            if (selectedRoutine.Children.Any())
            {
                var routineTree = _viewModel.SelectedRoutineTree;
                var subroutinesPage = new SubroutinesPage(routineTree, fragId, title, blobId, _projCompName);
                await Navigation.PushAsync(subroutinesPage);
            }
            else
            {
                var routinePage = new RoutinePage(title, blobId);
                await Navigation.PushAsync(routinePage);
            }

            //take away selected background
            ((ListView)sender).SelectedItem = null;
        }
    }
}

DataTemplateSelector

using MyApp.Pages.Routines.CustomCells;
using MyCloudContracts.DTOs;
using Xamarin.Forms;

namespace MyApp.Controls
{
    class RoutinesDataTemplateSelector : DataTemplateSelector
    {
        private readonly DataTemplate _folderDataTemplate;
        private readonly DataTemplate _routineDataTemplate;

        public RoutinesDataTemplateSelector()
        {
            _folderDataTemplate = new DataTemplate(typeof(FolderViewCell));
            _routineDataTemplate = new DataTemplate(typeof(RoutineViewCell));
        }

        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            var chooser = item as PublishedDocumentFragmentDTO;
            if (chooser == null)
                return null;
            else if (chooser.Children.Length == 0)
            {
                return _routineDataTemplate;
            }
            else
            {
                return _folderDataTemplate;
            }      
        }
    }
}

以及我的自定义 ViewCell 之一的示例。我认为这是我错的地方,但我不确定为什么。我制作了属性,但我不知道如何正确设置它们。

using Xamarin.Forms;

namespace MyApp.Pages.Routines.CustomCells
{
    public class RoutineViewCell : ViewCell
    {
        public static readonly BindableProperty TitleProperty =
            BindableProperty.Create("Title", typeof(string), typeof(RoutineViewCell), "");

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
    }
}

感谢您的帮助:)

我找到了答案。我需要覆盖自定义单元格文件中的 OnBindingContextChanged()。我的工作代码现在看起来像这样:

using Xamarin.Forms;

namespace MyApp.Pages.Routines.CustomCells
{
    public class RoutineViewCell : ViewCell
    {
        public static readonly BindableProperty TitleProperty =
            BindableProperty.Create("Title", typeof(string), typeof(RoutineViewCell), "");

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        protected override void OnBindingContextChanged()
        {
            this.SetBinding(TitleProperty, "Title");
            base.OnBindingContextChanged();
        }
    }
}