【问题标题】:How to pass event from ViewCell to parent object, where ListView is placed如何将事件从 ViewCell 传递到放置 ListView 的父对象
【发布时间】:2017-06-09 20:20:32
【问题描述】:

我想处理来自父对象中单元格的事件。这是父对象的 XAML:

<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App.Views.SomeView"
             xmlns:customViews="clr-namespace:App.Views;assembly=App"
             VerticalOptions="FillAndExpand">

  <ListView x:Name="MyList"
            HasUnevenRows="True"
            CachingStrategy="RecycleElement">

    <ListView.ItemTemplate>
      <DataTemplate>
        <customViews:CustomListItem/>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</StackLayout>

如您所见,我在数据模板中定义了一个自定义单元格。单元格本身看起来像这样:

<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="App.Views.CustomListItem">

    <Image x:Name="infoButton" Aspect="AspectFit" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />

</ViewCell>

在文件后面的代码中,我向图像添加了一个点击识别器:

public partial class CustomListItem : ViewCell
{
    private TapGestureRecognizer onIconTapppedRecognizer;

    public CustomListItem()
    {
        InitializeComponent();

        // Make it tapable
        this.onIconTapppedRecognizer = new TapGestureRecognizer();
        this.onIconTapppedRecognizer.Tapped += Icon_Tapped;
        this.infoButton.GestureRecognizers.Add(this.onIconTapppedRecognizer);
    }

    private async void Icon_Tapped(object sender, EventArgs e)
    {
        await MainPage.Instance.Detail.Navigation.PushAsync(new MyNewPage(this.viewModel));
    }
}

现在我想在SomeView 上接收Icon_Tapped 事件。 This approach 不起作用,因为单元格是在单独的对象中定义的,而不是在同一个“页面”上。 Another approach 需要通过构造函数在代码中传递视图模型,但我已经在 XAML 中定义了它。此外,我为列表视图中的每个条目都有一个模型,而不是整个列表视图的模型。

如何接收来自单元格的事件?

【问题讨论】:

  • 为什么不直接将事件添加到CustomListItem 并在SomeView 中处理呢?
  • 您是否特别想避免绑定回SomeView 的 ViewModel?您可以在 ListItem XAML 中添加 GestureRecognizer,并将其绑定回父级(即 ListView 的源或父级 ViewModel)的 BindingContext 中的命令。
  • @icebat:我应该在哪里订阅/取消订阅该活动?单元格在 XAML 中的 DataTemplate 中初始化。
  • @ctacke:我认为这是 MVVM 和没有 MVVM 的混合体......我看到了this code。你是这个意思吗?我如何将它绑定回来?
  • 有了你的布局,没有什么能阻止你在 XAML 中订阅。如果您打算提取 DataTemplate 以重用它,则可以改为制作路由事件并在 ListView 级别捕获它。没什么复杂的。

标签: c# xaml event-handling xamarin.forms


【解决方案1】:

不知道您可以在任何对象上定义自定义事件:

SomeView XAML 现在看起来像这样

<customViews:CustomListItem ButtonClicked="SomeView_ButtonClicked"/>

来自SomeView的代码隐藏文件中的相应事件处理程序

private async void SomeView_ButtonClicked(object sender, CustomEventArgs e)
{
    // do something
}

在我的ViewCell CustomListItem 我已经定义了一个这样的公共事件处理程序

public event EventHandler<CustomEventArgs> ButtonClicked;

并且从我添加的手势识别器的事件处理程序中调用此事件:

private void Icon_Tapped(object sender, EventArgs e)
{
    this.ButtonClicked?.Invoke(sender, new CustomEventArgs(this.model));
}

【讨论】:

  • 非常感谢分享!如何在 CustomListItem 类中获得对视图模型 (this.model) 的引用?
  • 我最终做了什么:像这样传递对我的视图模型的引用:this.ButtonClicked?.Invoke(sender, BindingContext as MyAwesomeViewModel);
  • @JannieTheunissen:很高兴你自己解决了这个问题。在OnBindingContextChanged() 我这样做var viewModel = BindingContext as MyAwesomeViewModel; 基本上是一样的。
猜你喜欢
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
相关资源
最近更新 更多