首页 > 解决方案 > Xamarin.Forms 自定义控件 BindingContext 在 DataTemplate 中不起作用?

问题描述

我正在尝试将 BindableLayout 与 StackLayout 一起使用来显示集合中的项目,但由于某种原因,绑定在使用 BindableLayout 时不起作用。在使用 XAML 热重新加载进行调试时,它有时会在重新加载后开始工作,但在刷新 UI 后不会继续工作。

如果需要, repo 在这里,但这是有问题的代码:

示例图像

页面 XAML:(自定义控件为 ComicInfoView)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:pages="clr-namespace:ComicBud.Pages"
         xmlns:views="clr-namespace:ComicBud.Views"
         mc:Ignorable="d"
         x:Class="ComicBud.Pages.HomePage"
         Title="ComicBud">

<ContentPage.ToolbarItems>
    <ToolbarItem IconImageSource="ic_add_white_36dp" Command="{Binding AddComicUrlCommand}" />
</ContentPage.ToolbarItems>

<ContentPage.Resources>
    <x:String x:Key="pageBorder">10</x:String>
</ContentPage.Resources>

<ContentPage.Content>
    <RefreshView IsRefreshing="{Binding IsRefreshing}"
                 Command="{Binding RefreshCommand}">
        <ScrollView Orientation="Vertical">
            <StackLayout Margin="0, 10, 0, 10">

                <StackLayout Orientation="Vertical"
                             IsVisible="{Binding IsAnyComics}">
                    <Label Text="Using BindableLayout"
                           FontSize="Subtitle"
                           Margin="10, 0, 10, 0"/>
                    <ScrollView Orientation="Horizontal"
                                HorizontalScrollBarVisibility="Never">
                        <StackLayout Orientation="Horizontal"
                                     Spacing="10"
                                     Padding="10, 5, 10, 5"
                                     BindableLayout.ItemsSource="{Binding Comics}">
                            <BindableLayout.ItemTemplate>
                                <DataTemplate>
                                    <views:ComicInfoView />
                                </DataTemplate>
                            </BindableLayout.ItemTemplate>
                        </StackLayout>
                    </ScrollView>
                </StackLayout>

                <StackLayout Orientation="Vertical"
                             IsVisible="{Binding IsAnyComics}">
                    <Label Text="Manual"
                           FontSize="Subtitle"
                           Margin="10, 0, 10, 0"/>
                    <ScrollView Orientation="Horizontal"
                                HorizontalScrollBarVisibility="Never">
                        <StackLayout Orientation="Horizontal"
                                     Spacing="10"
                                     Padding="10, 5, 10, 5">
                            <views:ComicInfoView />
                        </StackLayout>
                    </ScrollView>
                </StackLayout>

            </StackLayout>
        </ScrollView>
    </RefreshView>
</ContentPage.Content>

ComicInfoView.xaml:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:views="clr-namespace:ComicBud.Views"
         mc:Ignorable="d"
         x:Class="ComicBud.Views.ComicInfoView">

<ContentView.BindingContext>
    <views:ComicInfoViewModel />
</ContentView.BindingContext>

<ContentView.Content>
    <StackLayout Orientation="Horizontal">
        <Frame WidthRequest="60"
               HeightRequest="84"/>
        <StackLayout RelativeLayout.XConstraint=
                            "{ConstraintExpression Type=RelativeToParent,
                                                   Property=Width,
                                                   Factor=0,
                                                   Constant=100}"
                     Margin="0, 5, 10, 0"
                     Spacing="0">
            <Label Text="{Binding ComicName}"
                   HorizontalTextAlignment="Start"
                   FontSize="Subtitle"
                   LineBreakMode="WordWrap"
                   WidthRequest="100"/>
            <Label Text="Last Read"
                   HorizontalTextAlignment="Start"
                   FontSize="Micro"
                   Margin="0, 5, 0, 0"/>
            <Label Text="3 days ago"
                   HorizontalTextAlignment="Start"
                   FontSize="Small"/>
            <Label Text="Updated"
                   HorizontalTextAlignment="Start"
                   FontSize="Micro"
                   Margin="0, 5, 0, 0"/>
            <Label Text="2 days ago"
                   HorizontalTextAlignment="Start"
                   FontSize="Small"/>
        </StackLayout>

        <StackLayout.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding OpenComicCommand}"/>
        </StackLayout.GestureRecognizers>

    </StackLayout>
</ContentView.Content>

ComicInfoViewModel.cs

using System.ComponentModel;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using FreshMvvm;
using ComicBud.Pages;
using ComicBud.Systems;

namespace ComicBud.Views
{
public class ComicInfoViewModel : INotifyPropertyChanged
{
    public ComicInfoViewModel()
    {
        OpenComicCommand = new Command(async () => await OpenComic());
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private Comic _comic;

    public Comic Comic
    {
        get { return _comic; }
        set
        {
            _comic = value;

            OnPropertyChanged();
            OnPropertyChanged(nameof(ComicName));
        }
    }

    public string ComicName
    {
        get { return "Binding Is Working"; }
    }

    public Command OpenComicCommand { get; }

    private async Task OpenComic()
    {
        var navService = FreshIOC.Container.Resolve<IFreshNavigationService>(Constants.DefaultNavigationServiceName);
        var page = FreshPageModelResolver.ResolvePageModel<ComicDetailPageModel>();
        await navService.PushPage(page, null);
    }

    private void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
}

编辑:在 DataTemplate 中用一些东西(Frame、ContentView 等)包装 ComicInfoView 似乎可以解决它。像这样:

<BindableLayout.ItemTemplate>
     <DataTemplate>
           <ContentView>
                 <views:ComicInfoView/>
           </ContentView>
     </DataTemplate>
</BindableLayout.ItemTemplate>

我会将问题标记为已解决,但如果有人能解释为什么会这样,将不胜感激!

标签: c#xamlmvvmxamarin.forms

解决方案


推荐阅读