首页 文章

如何在ListView(Xamarin)中处理特定控件的事件

提问于
浏览
0

我有一个带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用于处理listview点击事件

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

与listview tapped事件不同,TapGestureRecognizer_Tapped无法轻松获取我需要处理某些逻辑的tapped项目 . 所以这是我的问题,如果我在GestureRecognizer事件方法中点击Listview中的控件,我该如何获取被点击的项目

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

2 回答

  • 2

    虽然你可以用一个事件来做,但我认为最好用 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 that Cell` .

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

    public Command TapCommand => new Command<Foo>((fooObject) => Tapped(fooObject));
    
    private void Tapped(Foo fooObject)
    {
        DisplayAlert("Tapped!", fooObject.Bar, "Gotcha");
    }
    

    在尖括号之间,您可以指定您期望的对象类型 . 你可以把它留下来 . 然后只需传递一个 object 就需要进行投射 .

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

  • 0

    杰拉德回答是答案 .

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

    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");
    
    }
    

    我尝试使用Code创建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;
    
        }
    }
    

相关问题