Detecting tap on label, inside ViewCell, inside ListView
我正在尝试处理类似的事情(从UI角度来看),以:
为了为以下两种调用两种不同的业务逻辑:
- 点击ViewCell元素本身(在ListView中)-在示例中导航到其他页面
- 点击Label元素(可点击的标签),该元素位于给定的ViewCell元素内-在示例中,删除给定的对象或其他
我想在ViewModel页面中包含整个"点击"逻辑。
根据Xamarin论坛提出的建议,我能够调用一些逻辑来"点击"我从单元格中删除操作,但是直接在我的数据模型内部进行调用-在我的PoV中这不是一个很好的解决方案,因为我想操纵List集合(因此,最可取的方式是在ViewModel页面上使用此逻辑。
我现在所拥有的:
我的页面查看XAML代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App.Views.TestView"> <ContentPage.Content> <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <ListView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding MyItemsCollection}" SelectedItem="{Binding SelectedItem}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal"> <!-- Name Label --> <Label Text="{Binding Name}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" /> <!-- Delete"Icon" --> <Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding OnClickableLabel}" CommandParameter="{Binding .}" /> </Label.GestureRecognizers> </Label> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage> |
我的页面View C#代码看起来像(这里没有特定的代码,除了将** BindingContext *绑定到页面ViewModel之外):
1 2 3 4 5 6 7 8 | public partial class TestView : ContentPage { public TestView() { InitializeComponent(); BindingContext = ServiceLocator.Current.GetInstance<TestViewModel>(); } } |
我的页面ViewModel C#代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | public class TestViewModel : ViewModelBase { public TestViewModel() { MyItemsCollection = GetMyItemsCollection(); } private List<MyItem> GetMyItemsCollection() { return new List<MyItem> { new MyItem { ID = 1L, Name ="Item 1 Name" }, new MyItem { ID = 2L, Name ="Item 2 Name" }, new MyItem { ID = 3L, Name ="Item 3 Name" } }; } private List<MyItem> _myItemsCollection { get; set; } public List<MyItem> MyItemsCollection { get { return _myItemsCollection; } set { _myItemsCollection = value; RaisePropertyChanged(); } } private MyItem _SelectedItem { get; set; } public MyItem SelectedItem { get { return _SelectedItem; } set { if (_SelectedItem != value) { _SelectedItem = value; RaisePropertyChanged(); Debug.WriteLine("SelectedItem:" + _SelectedItem.Name); } } } private RelayCommand<object> _OnClickableLabel; public RelayCommand<object> OnClickableLabel { get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); } } private void Test(object currentObject) { Debug.WriteLine("This should work... but it's not working :("); } } |
我的数据模型代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class MyItem { public long ID { get; set; } public string Name { get; set; } private RelayCommand<object> _OnClickableLabel; public RelayCommand<object> OnClickableLabel { get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); } } private void Test(object currentObject) { Debug.WriteLine("This works... but it's not good idea, to have it here..."); } } |
为了直接在页面ViewModel内调用OnClickableLabel,需要更改什么?
我知道,这是错误的:
1 | <TapGestureRecognizer Command="{Binding OnClickableLabel}" CommandParameter="{Binding .}" /> |
但不知道什么:/。
救命!非常感谢。
好的,我通过扩展XAML代码找到了解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App.Views.TestView" x:Name="Page"> <ContentPage.Content> <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <ListView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding MyItemsCollection}" SelectedItem="{Binding SelectedItem}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal"> <!-- Name Label --> <Label Text="{Binding Name}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" /> <!-- Delete"Icon" --> <Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding Path=BindingContext.OnClickableLabel, Source={x:Reference Page}}" CommandParameter="{Binding .}" /> </Label.GestureRecognizers> </Label> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage> |
之后,按预期方式,我在页面ViewModel中调用了OnClickableLabel命令:)。
如果有人知道"更好"的解决方案(从XAML代码的角度来看更好),我想看看它;)。
非常感谢大家!
继续@Namek所说的,我建议我首先获取列表视图项的对象,然后调用命令或viewmodel方法。
有关更多信息,请参阅https://adityadeshpandeadi.wordpress.com/2018/07/15/the-more-interactive-listview/上有关交互式Listview的博客文章
随便看看。 :)