【问题标题】:How to handle event for a specific control in ListView(Xamarin)如何处理 ListView(Xamarin) 中特定控件的事件
【发布时间】:2018-02-06 15:41:44
【问题描述】:

我有一个带有 ViewCell 的 Listview,在这个 ViewCell 中有 3 个图像和 3 个标签。为了处理点击事件,我为每个控件编写了一个 GestureRecognizers。

<ListView HasUnevenRows="True"
            SeparatorColor="White"
            ItemsSource="{Binding List}"
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
            ItemSelected="Handle_ItemSelected"
            ItemTapped="ListView_ItemTapped">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Spacing="0">
                            <StackLayout Orientation="Horizontal" Padding="16,8,16,4">
                                <Image Source="{Binding IconImageSource}" HeightRequest="36" WidthRequest="36"/>
                                <StackLayout HorizontalOptions="StartAndExpand" Padding="8,0,0,0" Spacing="0">
                                    <Label Text="{Binding LocalizedText}" TextColor="White"/>
                                    <Label Text="{Binding Value}" TextColor="Gray" FontSize="Small"/>
                                </StackLayout>
                            </StackLayout>
                            <BoxView Color="WhiteSmoke" HeightRequest="1" HorizontalOptions="FillAndExpand" Opacity="0,5" />
                            <RelativeLayout Padding="0,4,0,4" >
                                <Image Source="ic_ecu_eye"
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.25}"
                                       RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0, Constant=4}"
                                       />
                                <Label Text="{Binding ViewedCount}" 
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.25, Constant=20}" />
                                <Image Source="ic_ecu_favorite" 
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}"
                                       RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0, Constant=4}"/>
                                <Label Text="{Binding FavoriteCount}" 
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=20}" />
                                <Image Source="ic_ecu_comment"  
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.75}"
                                       RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0, Constant=4}">

                                    <Image.GestureRecognizers>
                                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"   NumberOfTapsRequired="1"/>
                                    </Image.GestureRecognizers>
                                </Image>
                                <Label Text="{Binding CommentsCount}" 
                                       RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.75, Constant=20}">
                                     <Label.GestureRecognizers>
                                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"  NumberOfTapsRequired="1"/>
                                    </Label.GestureRecognizers> 
                                </Label>
                            </RelativeLayout>
                        </StackLayout>


                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

代码隐藏

async private void TapGestureRecognizer_Tapped(object sender, System.EventArgs e)
    { 
        // want to get listview item
    }

ListView_ItemTapped 用于处理列表视图的点击事件

async private void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
    { // easily get the tapped item via e.Item   }

与 listview 点按事件不同,TapGestureRecognizer_Tapped 无法轻松获取点按项,我需要处理一些背后的逻辑。 所以这就是我的问题,如果我在 GestureRecognizer 事件方法中的 Listview 中点击一个控件,我如何获得被点击的项目,比如这里

async private void TapGestureRecognizer_Tapped(object sender, System.EventArgs e)
    { 
        // TODO:
    }

【问题讨论】:

  • 如果你想切换到Command,你可以使用CommandParameter
  • 你必须直接点击你的图片。或者你可以试试带图片的按钮,也可以设置CommandParameter

标签: listview xamarin.forms


【解决方案1】:

虽然您可以通过事件来执行此操作,但我认为最好使用TapGestureRecognizer 中的Command 属性来执行此操作。我为您创建了一个示例项目来演示这一点。你可以找到它here

删除Tapped 属性并开始使用Command,如下所示。

<Label.GestureRecognizers>
    <TapGestureRecognizer Command="{Binding Path=BindingContext.TapCommand, Source={x:Reference Name=ThaPage}" CommandParameter="{Binding .}" />
</Label.GestureRecognizers>

您会注意到Command 需要一些工作。这是因为ListViewBindingContext 将是单元格绑定到的项目。虽然您希望命令位于页面的BindingContext 上。这样做会从“ThaPage”的 BindingContext 中读取 Command。不要忘记为您的页面提供x:Name="ThaPage" 属性。你可能会想一个更好的名字。

其次,有CommandParameter。通过在其中插入{Binding .} here. You bind the actual object of the item bound to thatCell`。

现在在BindingContext 中,像这样定义Command

public Command TapCommand => new Command<Foo>((fooObject) => Tapped(fooObject));

private void Tapped(Foo fooObject)
{
    DisplayAlert("Tapped!", fooObject.Bar, "Gotcha");
}

在尖括号之间,您可以指定您期望的对象类型。你可以把它排除在外。然后将只传递一个object,您需要进行强制转换。

然后在处理Command 的方法中,您将可以使用被点击的对象。我的对象是Foo,仅用于此示例。

【讨论】:

  • 谢谢。当我运行该示例时,我得到了类似“xxx.ViewModel”上未找到的“Command”属性。我应该为 TapCommand 声明一个 BindableProperty 吗?
【解决方案2】:

杰拉德的答案就是答案。

顺便说一句,我想你可以试试

async private void TapGestureRecognizer_Tapped(object sender, System.EventArgs e)
{ 
    // want to get listview item
    await Application.Current.MainPage.DisplayAlert("Article", ((YourModel)this.BindingContext).YourField, "Ok");

}

我已尝试使用代码创建 ViewCell,它可以正常工作。我不知道您是否在使用 XAML 创建 ViewCell 时遇到问题。

这是我的 ViewCell 的完整代码

class ListViewTemplateGrid : ViewCell
{
    public ListViewTemplateGrid(){

        TapGestureRecognizer tgr = new TapGestureRecognizer();
        tgr.Tapped += async (object sender, EventArgs e) => {

            try {

                await Application.Current.MainPage.DisplayAlert("Article", ((ListViewModel)this.BindingContext).Description, "Ok");

            }
            catch(Exception ex){

                await Application.Current.MainPage.DisplayAlert("Error", ex.Message, "Ok");
            }

        };

        Label labelDescription = new Label() {VerticalOptions = LayoutOptions.Center};
        labelDescription.SetBinding(Label.TextProperty, "Description");
        labelDescription.GestureRecognizers.Add(tgr);

        Label labelQty = new Label() { VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
        labelQty.SetBinding(Label.TextProperty, "Qty");

        Label labelOrdered = new Label() { VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
        labelOrdered.SetBinding(Label.TextProperty, "Ordered");

        // Add controls to the grid
        Grid grid = CreateGrid();
        grid.Children.Add(labelDescription, 0,1,0,1);
        grid.Children.Add(SeparatorV(), 1, 2, 0, 1);
        grid.Children.Add(labelQty, 2, 3, 0, 1);
        grid.Children.Add(SeparatorV(), 3, 4, 0, 1);
        grid.Children.Add(labelOrdered, 4, 5, 0, 1);

        grid.Children.Add(SeparatorH(), 0, 5, 1, 2);

        this.View = grid;

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-16
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2013-07-24
    相关资源
    最近更新 更多