C# 使用PangestureRecognitizer的表单-在UWP上移出窗口区域不会触发状态取消或完成

C# 使用PangestureRecognitizer的表单-在UWP上移出窗口区域不会触发状态取消或完成,c#,uwp,xamarin.forms,uipangesturerecognizer,C#,Uwp,Xamarin.forms,Uipangesturerecognizer,我的问题是关于Xamarin.Forms上的PangestureRecognitor,特别是UWP上的。平移手势效果很好,菜单会滑入滑出,但如果将鼠标光标移到应用程序窗口之外,则不会触发GestureStatus.Cancelled或GestureStatus.Completed。我简化了下面的代码,因为它并不重要。平移手势工作正常,菜单随平移滑入滑出。问题是,如果将光标移到应用程序窗口之外,它不会触发任何内容 代码如下: panContainer是一个简单的ContentView var pa

我的问题是关于Xamarin.Forms上的PangestureRecognitor,特别是UWP上的。平移手势效果很好,菜单会滑入滑出,但如果将鼠标光标移到应用程序窗口之外,则不会触发GestureStatus.Cancelled或GestureStatus.Completed。我简化了下面的代码,因为它并不重要。平移手势工作正常,菜单随平移滑入滑出。问题是,如果将光标移到应用程序窗口之外,它不会触发任何内容

代码如下:

panContainer是一个简单的ContentView

var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += PanUpdated;
panContainer.GestureRecognizers.Add(panGesture);

private void PanUpdated(object sender,PanUpdatedEventArgs e) {
        switch(e.StatusType) {
            case GestureStatus.Started:
                break;
            case GestureStatus.Running:
                menuLayout.TranslationX = (float)e.TotalX;
                break;
            case GestureStatus.Completed:
            case GestureStatus.Canceled:  //I assumed this would be called!
                if(menuLayout.TranslationX < 100) {
                    Close();
                } else {
                    Open();
                }
                break;
        }
    }
var pangestrue=新的pangestruerecognizer();
pangestrue.PanUpdated+=PanUpdated;
panContainer.GestureRecogeners.Add(panGesture);
私有void PanUpdated(对象发送方,PanUpdatedEventArgs e){
开关(如状态类型){
案例手势状态。已启动:
打破
案例手势状态。正在运行:
menuLayout.TranslationX=(float)e.TotalX;
打破
案例管理状态。已完成:
case GestureStatus.Cancelled://我以为这会被调用!
if(menuLayout.TranslationX<100){
Close();
}否则{
Open();
}
打破
}
}
提前谢谢

如果将鼠标光标移到应用程序窗口之外,则不会触发GestureStatus.Cancelled或GestureStatus.Completed。我简化了下面的代码,因为它并不重要。平移手势工作正常,菜单随平移滑入滑出。问题是,如果将光标移到应用程序窗口之外,它不会触发任何内容

我已经测试了你的代码并重现了这个问题。我试图在源代码中找到问题的原因。我找到了

指针退出
操作完成
等时,将调用
PanComplete
方法,但当指针退出时未调用该方法。然后我尝试在uwp原生项目中测试
点退出
操作完成
事件。两者都工作正常

<Border Width="200" Height="200"  Background="Red" PointerEntered="Border_PointerEntered" PointerExited="Border_PointerExited" ManipulationCompleted="Border_ManipulationCompleted"/>


因此,xamarin可能存在一些问题。

根据前面的评论,可行的解决方案

//Shared part
public class PanOutsideWindowEffect : RoutingEffect
{
    public event EventHandler<PanUpdatedEventArgs> PanUpdated;

    public PanOutsideWindowEffect() : base($"{ResolutionGroupName.Organization}.{nameof(PanOutsideWindowEffect)}")
    {
    }

    public void SendPanCancel()
    {
        PanUpdated?.Invoke(this, new PanUpdatedEventArgs(GestureStatus.Canceled, 0));
    }
}

//UWP part
public class PanOutsideWindowEffect : PlatformEffect
{
    private FrameworkElement frameworkElement;
    private MobileApp.Effects.PanOutsideWindowEffect effect;

    protected override void OnAttached()
    {
        frameworkElement = Control == null ? Container : Control;
        effect = (MobileApp.Effects.PanOutsideWindowEffect)Element.Effects.First(e => e is MobileApp.Effects.PanOutsideWindowEffect);

        if (frameworkElement != null)
        {
            frameworkElement.PointerExited += OnPointerExited;
        }
    }

    protected override void OnDetached()
    {
        if (frameworkElement != null)
        {
            frameworkElement.PointerExited -= OnPointerExited;
        }
    }

    private void OnPointerExited(object sender, PointerRoutedEventArgs args)
    {
        effect?.SendPanCancel();
    }
}
//共享部分
公共类PanOutsideWindowEffect:路由效果
{
公共事件事件处理程序更新;
公共PanOutsideWindowEffect():基($“{ResolutionGroupName.Organization}.{nameof(PanOutsideWindowEffect)}”)
{
}
公共无效SendPanCancel()
{
PanUpdated?.Invoke(这是新的PanUpdatedEventArgs(GestureStatus.cancelled,0));
}
}
//超宽带部分
公共类PanOutsideWindowEffect:PlatformEffect
{
私有框架元素框架元素;
私人手机app.Effects.panoutsidewindoweffects;
受保护的覆盖无效附加()
{
frameworkElement=Control==null?容器:控件;
effect=(MobileApp.Effects.PanOutsideWindowEffect)Element.Effects.First(e=>e是MobileApp.Effects.PanOutsideWindowEffect);
if(frameworkElement!=null)
{
frameworkElement.PointerExited+=OnPointerExited;
}
}
受保护的覆盖无效OnDetached()
{
if(frameworkElement!=null)
{
frameworkElement.PointerExit-=OnPointerExit;
}
}
私有void OnPointerExited(对象发送方,PointerRoutedEventArgs args args)
{
效果?.SendPanCancel();
}
}

谢谢您的回复。
//Shared part
public class PanOutsideWindowEffect : RoutingEffect
{
    public event EventHandler<PanUpdatedEventArgs> PanUpdated;

    public PanOutsideWindowEffect() : base($"{ResolutionGroupName.Organization}.{nameof(PanOutsideWindowEffect)}")
    {
    }

    public void SendPanCancel()
    {
        PanUpdated?.Invoke(this, new PanUpdatedEventArgs(GestureStatus.Canceled, 0));
    }
}

//UWP part
public class PanOutsideWindowEffect : PlatformEffect
{
    private FrameworkElement frameworkElement;
    private MobileApp.Effects.PanOutsideWindowEffect effect;

    protected override void OnAttached()
    {
        frameworkElement = Control == null ? Container : Control;
        effect = (MobileApp.Effects.PanOutsideWindowEffect)Element.Effects.First(e => e is MobileApp.Effects.PanOutsideWindowEffect);

        if (frameworkElement != null)
        {
            frameworkElement.PointerExited += OnPointerExited;
        }
    }

    protected override void OnDetached()
    {
        if (frameworkElement != null)
        {
            frameworkElement.PointerExited -= OnPointerExited;
        }
    }

    private void OnPointerExited(object sender, PointerRoutedEventArgs args)
    {
        effect?.SendPanCancel();
    }
}