【发布时间】:2021-01-16 23:14:18
【问题描述】:
我已经对这个问题进行了很多搜索,坦率地说,我对此很感兴趣。我有一个聊天应用程序。在这个应用程序上有一个视图,其中有来自我和其他聊天成员的消息。从技术上讲,它是一个带有 ItemTemplate 的 ListView,它有一个 Binded 类(DataTemplateSelector),它根据规则返回 ViewCells(无论要显示的消息是 MINE 还是 OTHERS)
消息(入站或出站)位于单独的文件中。
目前,TapGestureRecognizer 不工作,ChooseNameToMentionCommand 命令未触发
有很多“类似”的问题是 TapGestureRecognizer 不能像这样在 ListView 上工作:
TapGestureRecognizer not working inside ListView
那里(以及任何其他相关主题)命令不起作用的答案是:
- 在您的命令绑定上使用
Source={x:Reference MessagesListView}
但是当我使用这个建议时,我的结尾是:
Xamarin.Forms.Xaml.XamlParseException: 'Position 30:21. Can not find the object referenced by MessagesListView'
我如何在我的情况下使用它(ViewCell 在单独的文件中定义)重要说明 - 我正在使用 MVVM 方法并且不想在 ViewCell 的代码隐藏中做任何事情(然后我什至可以使用 Tapped 事件。我已经测试过了。当然这种方法有效:) )
这是我的代码:
MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableRangeCollection<MessageModel> Messages { get; set; }
public Command ChooseNameToMentionCommand { get; set; }
public string NewMessage {get; set;}
public MainViewModel()
{
Messages = new ObservableRangeCollection<MessageModel>();
ChooseNameToMentionCommand = new Command<string>(async (t) => await ChooseNameToMention(t));
}
private Task ChooseNameToMention(string name)
{
this.NewMessage += $"@{name}";
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="Chat.ClientLibrary.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:Chat.ClientLibrary.Converters"
xmlns:local="clr-namespace:Chat.ClientLibrary.CustomCells"
xmlns:partials="clr-namespace:Chat.ClientLibrary.Views.Partials"
BackgroundColor="White"
x:Name="MainChatPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:MyDataTemplateSelector x:Key="MessageTemplateSelector"/>
</ResourceDictionary>
</ContentPage.Resources>
/* REMOVED UNNECESSARY code */
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView
Grid.Row="1"
FlowDirection="RightToLeft"
Rotation="180"
x:Name="MessagesListView"
ItemTemplate="{StaticResource MessageTemplateSelector}"
ItemsSource="{Binding Messages}"
HasUnevenRows="True"
ItemSelected="MyListView_OnItemSelected"
ItemTapped="MyListView_OnItemTapped"
SeparatorVisibility="None" />
/* REMOVED UNNECESSARY code */
</Grid>
</ContentPage>
MyDataTemplateSelector.cs
class MyDataTemplateSelector : DataTemplateSelector
{
public MyDataTemplateSelector()
{
// Retain instances!
this.incomingDataTemplate = new DataTemplate(typeof(IncomingViewCell));
this.outgoingDataTemplate = new DataTemplate(typeof(OutgoingViewCell));
}
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
var messageVm = item as MessageModel;
if (messageVm == null)
return null;
return messageVm.IsOwnMessage ? this.incomingDataTemplate : this.outgoingDataTemplate;
}
private readonly DataTemplate incomingDataTemplate;
private readonly DataTemplate outgoingDataTemplate;
}
IncomingViewCell.xaml(我不会发布 OutgoingViewCell - 它几乎是一样的;)不同的颜色)
<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Chat.ClientLibrary.Views.CustomCells.IncomingViewCell"
xmlns:forms9patch="clr-namespace:Forms9Patch;assembly=Forms9Patch">
<Grid ColumnSpacing="2"
Padding="5"
FlowDirection="LeftToRight"
Rotation="180"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="40"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="1" HorizontalTextAlignment="Start" Text="{Binding UserName}" TextColor="Blue">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path= BindingContext.ChooseNameToMentionCommand, Source={x:Reference MessagesListView}}" CommandParameter="{Binding UserName}" />
</Label.GestureRecognizers>
</Label>
/* REMOVED UNNECESSARY code */
</Grid>
</ViewCell>
[编辑 12:12 01.10.2020] 我忘了把 MainPage.cs 放在这里,所以这里是:
MainPage.cs
public partial class MainPage : ContentPage
{
MainViewModel vm;
public MainPage()
{
this.BindingContext = vm = new MainViewModel();
InitializeComponent();
}
void MyListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
MessagesListView.SelectedItem = null;
}
void MyListView_OnItemTapped(object sender, ItemTappedEventArgs e)
{
MessagesListView.SelectedItem = null;
}
}
添加了 ListOnItemTapped 事件(我忘了它 - 因为它取自一些聊天示例。但我不认为它会破坏任何东西。当我直接为 Label 添加 OnTapped 时 - 它确实有效.
【问题讨论】:
-
发布示例 git repo 的链接以查看
-
它只在私人仓库中。我已经发布了代码中最重要的部分。
-
你可以做一个示例回购,我无法从这里得到问题
-
@ShubhamTyagi - 问题完全来自下面的响应(Wendy Zang - MSFT)在他发布的状态下 - 它正在工作。但是,如果您将这些模板复制粘贴到单独的文件中(例如,您将拥有数百个模板,并且您不想在主 xaml 中创建混乱),那么它不起作用 - 给出消息:“Xamarin.Forms.Xaml。 XamlParseException: '位置 30:21。找不到 MessagesListView 引用的对象'"
标签: c# listview xamarin xamarin.forms uitapgesturerecognizer