需要修复:无法从 Listview-DataTemplate-ViewCell 内的自定义控件内的按钮打开模式

Need Fix: Cannot open modal from button inside a Custom control inside Listview-DataTemplate-ViewCell

我有一个奇怪的问题,但可能是因为我不明白。我创建了 2 个自定义控件。 [Custom Control A] 有一个名为 [LAUNCH] 的按钮,用于启动模式。 [自定义控件 B] 没有按钮,但里面有自定义控件 A。

我用 [Custom Control B] 创建了一个页面,但是当我单击 [LAUNCH] 时,在调试时它会转到代码行 await Navigation.PushModalAsync(new ModalPage()) 但在那之后,它不会启动模式。

我尝试添加 [Customer Control A] 并单击 [LAUNCH],它能够显示模式。

我需要做些什么才能从自定义控件 B 打开模式吗?

编辑:经过进一步检查,我忘了提及 [Custom Control B] 是我为列表视图的项目模板绑定的控件。我再次测试只是加载一个没有列表视图的 [Custom Control B] 并且它能够打开模态。但是,当我将它作为项目模板放回列表视图中时,问题仍然存在。我需要为此做些什么才能 运行 吗?还是不可能?

编辑 2:制作了一个新的示例项目并隔离了案例,看起来它确实阻止了模态打开。

[自定义控件 A]

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestXamarin.Controls.CustomControlA">
  <ContentView.Content>
        <Grid BackgroundColor="AliceBlue" HeightRequest="300">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <FlexLayout Grid.Column="0"
                    Grid.Row="0"
                    Grid.RowSpan="2"/>
            <Button x:Name="btnOpen"
                    Text="Try Open Modal"
                    Clicked="BtnOpen_Clicked"
                    Grid.Column="1"
                    Grid.Row="0"/>
        </Grid>
    </ContentView.Content>
</ContentView>

[自定义控件 A].cs

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CustomControlA : ContentView
    {
        public CustomControlA()
        {
            InitializeComponent();
        }

        private async void BtnOpen_Clicked(object sender, EventArgs e)
        {
            await Navigation.PushModalAsync(new Modal());
        }
    }

[自定义控件 B]

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:TestXamarin.Controls"
             x:Class="TestXamarin.Controls.CustomControlB">
  <ContentView.Content>
        <Frame BorderColor="Accent"
               HeightRequest="300"
               WidthRequest="300">
            <controls:CustomControlA
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand"></controls:CustomControlA>
        </Frame>
  </ContentView.Content>
</ContentView>

[自定义控件 B].cs

[XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CustomControlB : ContentView
    {
        public CustomControlB()
        {
            InitializeComponent();
        }
    }

[主页]

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TestXamarin"
             xmlns:controls="clr-namespace:TestXamarin.Controls"
             x:Class="TestXamarin.MainPage">
    <ListView x:Name="listSample"
              HasUnevenRows="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <controls:CustomControlB/>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</ContentPage>

[主页].cs

   public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            var list = Enumerable.Range(1, 10).ToList();

            listSample.ItemsSource = list;
        }


    }

我找到了解决方案。看起来按钮只有在来自 ListView 项目的上下文时才有效。

所以我为自定义控件 A 和自定义控件 B 创建了一个命令绑定 属性,并在 ListView 项的 ViewModel 上创建了一个打开模态框的命令。然后我就可以通过命令打开模态了。

你也可以像这样调用推送模式页面(我认为它应该指定导航堆栈):

在您的 BtnOpen_Clicked 方法中:

private async void BtnOpen_Clicked(object sender, EventArgs e)
   {
      await App.Current.MainPage.Navigation.PushModalAsync(new Modal());
   }