在 Xamarin Forms 的 Telerik ListView 中,如何处理 Windows 上元素的右键单击事件?

In a Telerik ListView in Xamarin Forms, how do I handle a right click event for an element on Windows?

我公司有一个跨平台应用程序,主要用于使用 Xamarin 的移动设备以及 Telerik 的一些控件。最近,我们一直在投入更多工作以使其在所有平台上正常工作(它最初是 Android Java 应用程序的端口)。目前的症结是 Windows:尽管几乎所有功能都运行良好,但 Telerik ListView 给我们带来了麻烦。

我们目前使用长按事件来显示 UI 删除项目。这非常有效。这是在 Telerik ListView 中使用 GestureRecognizer。问题是我们找不到用鼠标获得类似行为的方法:单击该项目具有我们希望保留的效果,并且它已经包含一个不可替代的复选框。理想情况下,我会设置一个右键单击事件并完成它,但 Telerik ListView 控件上没有可用的右键单击事件。由于控件不是 UIElement,我无法以我习惯的任何方式找到它的子元素,而且节点本身似乎在运行时在实时可视化树中被替换。

我可以看到一个 ExtendedListViewItem 控件,它似乎是我想要提供鼠标事件处理程序的控件,但我不知道如何从顶部引用这些节点。它变得更加棘手,因为这些页面都在 .NET Standard 2.0 class 库中,所以任何特定于平台的代码(比如 VisualTreeHelper)只能添加到 UWP 应用程序,然后以某种方式抽象回这个库共享 UI.

我知道这是一个非常具体的问题,可能很难回答,但搜索我正在尝试做的任何部分似乎都能给我提供大量不相关的指南和信息。

我评估了在 RadListView 组件的 UWP 部分创建 'RightClicked' 事件并将该通知提供给控件的 XamarinForms 部分的方法。从技术上讲这是可能的,但在编写 UWP 相关 class 时应该提供通知是内部的。这意味着无法使用 UWP ListViewItems 提供该通知。

因为,您很可能已经在 XamarinForms 中为 RadListView 设置了自定义 ItemTemplate,您可以考虑创建自定义 XamrinForms 控件(例如 Grid、Frame、Border、Label。 ..) 具有 UWP 的自定义渲染器。该渲染器可以订阅 UIElement.RightTapped Event 并将通知重新传输到控件的 XamarinForms 部分。

public class MyRightClickGridRenderer : ViewRenderer<MyRightClickGrid, Grid>
{
    protected override void OnElementChanged(ElementChangedEventArgs<MyRightClickGrid> e)
    {
        if (this.Element != null)
        {
            if (this.Control == null)
            {
                var uwpGrid = new Grid { IsRightTapEnabled = true, Background = new SolidColorBrush(Colors.Transparent) };
                uwpGrid.RightTapped += UwpGrid_RightTapped;
                this.SetNativeControl(uwpGrid);
            }
        }
        if (this.Element == null)
        {
            if (this.Control != null)
            {
                ((Grid)this.Control).RightTapped -= UwpGrid_RightTapped;
            }
        }
    }

    private void UwpGrid_RightTapped(object sender, Windows.UI.Xaml.Input.RightTappedRoutedEventArgs e)
    {
        ((MyRightClickGrid)this.Element).RaiseRightClicked(sender);
    }
}

在 XamarinForms 项目中,您可以创建类似的东西

public class MyRightClickGrid : Grid
{
    public event EventHandler<TappedEventArgs> RightTapped;
    public void RaiseRightClicked(object sender)
    {
        this.RightTapped?.Invoke(this, new TappedEventArgs(null));
    }
}

创建此控件后,您可以像这样在 XAML 中使用它:

<telerikListView:RadListView>
  <telerikListView:RadListView.ItemTemplate>
    <DataTemplate>
      <telerikListViewPrimitives:ListViewTemplateCell>
        <telerikListViewPrimitives:ListViewTemplateCell.View>
          <MyNamespace:MyRightClickGrid >
            ***
          </MyNamespace:MyRightClickGrid >
        </telerikListViewPrimitives:ListViewTemplateCell.View>
      </telerikListViewPrimitives:ListViewTemplateCell>
    </DataTemplate>
  </telerikListView:RadListView.ItemTemplate>
</telerikListView:RadListView>

让我知道这是否适合你。

P.S。这种方法的一个优点是您可以使用相同的渲染器来检索点击发起的位置。 XamarinForms 仍然不支持此功能,您应该为每个平台创建类似的逻辑以获取该信息。