如果没有收到ButtonDown,WP7会丢弃MouseLeftButtonUp

时间:2012-01-07 21:24:12

标签: windows-phone-7

我正在尝试获取一个元素来触发MouseUp事件,当用户点击/点击它之外,拖入它,然后放手。此类功能适用于Silverlight,但不适用于WP7。我无法弄清楚如何让它在WP7中运行。

我创建了一个演示此功能的简单应用。在一个全新的WP7应用程序中,我将其添加到内容面板中:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
  <Grid.RowDefinitions> 
    <RowDefinition /> 
    <RowDefinition /> 
  </Grid.RowDefinitions> 
  <Grid x:Name="g1" MouseLeftButtonUp="Grid_MouseLeftButtonUp" Background="Green" /> 
  <Grid x:Name="g2" Grid.Row="1" MouseLeftButtonUp="Grid_MouseLeftButtonUp" Background="Blue" /> 
</Grid>

然后是代码隐藏中的Grid_MouseLeftButtonUp处理程序:

private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
  System.Diagnostics.Debug.WriteLine("MouseUp in " + (sender as Grid).Name);
  (sender as Grid).Background = new SolidColorBrush(Colors.Red);
}

运行此应用程序并注意如果您在按下的同一单元格中释放按钮,则MouseUp事件会正常触发,但如果您从一个单元格拖动到另一个单元格,则不会触发。如何激活MouseUp事件?

P.S。我也在app-hub表单上发布了这个,但还没有回复:http://forums.create.msdn.com/forums/p/98004/584400.aspx

4 个答案:

答案 0 :(得分:2)

解决此问题的一种方法是使用TouchFrame侦听TouchAction.Up。您必须使用TouchPoints的位置属性计算ButtonUp协同使用的UIElement,如下所述:http://forums.create.msdn.com/forums/p/98004/584465.aspx#584465

另一种方法是在ButtonDown UIElement中捕获鼠标。这将导致ButtonUp正确触发,但发件人将是导致ButtonDown的原始UIElement。您可以使用MouseEnter和MouseLeave跟踪鼠标移动的元素。这里简要介绍了鼠标捕获的必要性:http://forums.create.msdn.com/forums/p/70785/431882.aspx

答案 1 :(得分:2)

我的解决方案有点像ShawnFeatherly,但没有TouchFrame。

基本上,正如他所说,如果从发生MouseDown事件的网格中调用MouseCapture,MouseUp将在同一网格上触发。因此,我们知道如何在MouseUp发生时得到通知,唯一的问题是如何知道MouseUp实际发生在哪个网格中。 为此,我们将使用VisualTreeHelper.FindElementsInHostCoordinates方法,因为它返回指定坐标处的所有元素。

因此,首先向每个网格添加一个MouseLeftButtonDown事件处理程序:

    private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        ((Grid)sender).CaptureMouse();
    }

现在,在每个网格的MouseLeftButtonUp事件处理程序中,首先释放鼠标捕获,然后检索发生MouseUp的网格:

    private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        var grid = (Grid)sender;

        grid.ReleaseMouseCapture();

        var mouseUpGrid = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(this), this.ContentPanel)
            .OfType<Grid>()
            .FirstOrDefault();

        if (mouseUpGrid != null)
        {
            Debug.WriteLine("MouseUp in " + mouseUpGrid.Name);
            mouseUpGrid.Background = new SolidColorBrush(Colors.Red);
        }
    }

请注意,根据您的可视树可能会出现问题:如果您有多个网格并且只想在某些网格上检测MouseUp,则需要一种方法来识别它们。为此,我建议使用Tag属性。 Tag是每个控件上可用的通用字段,您可以根据需要使用它。它对于识别目的特别有用。

首先将其添加到您感兴趣的网格中:

<Grid x:Name="ContentPanel"
      Grid.Row="1"
      Margin="12,0,12,0"
      MouseLeftButtonUp="ContentPanel_MouseLeftButtonUp">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid x:Name="g1"
          Background="Green"
          MouseLeftButtonDown="Grid_MouseLeftButtonDown"
          MouseLeftButtonUp="Grid_MouseLeftButtonUp"
          Tag="dragdrop" />
    <Grid x:Name="g2"
          Grid.Row="1"
          Background="Blue"
          MouseLeftButtonDown="Grid_MouseLeftButtonDown"
          MouseLeftButtonUp="Grid_MouseLeftButtonUp"
          Tag="dragdrop" />
</Grid>

然后在代码隐藏中使用完全相同的逻辑,但这次在浏览可视化树时添加了一个过滤器:

    private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        var grid = (Grid)sender;

        grid.ReleaseMouseCapture();

        var mouseUpGrid = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(this), this.ContentPanel)
            .OfType<Grid>()
            .FirstOrDefault(element => element.Tag is string && (string)element.Tag == "dragdrop");


        if (mouseUpGrid != null)
        {
            Debug.WriteLine("MouseUp in " + mouseUpGrid.Name);
            mouseUpGrid.Background = new SolidColorBrush(Colors.Red);
        }
    }

你已经完成了!此代码应该能够处理复杂的情况,如:

<Grid x:Name="ContentPanel"
      Grid.Row="1"
      Margin="12,0,12,0"
      MouseLeftButtonUp="ContentPanel_MouseLeftButtonUp">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid x:Name="g1"
          Background="Green"
          MouseLeftButtonDown="Grid_MouseLeftButtonDown"
          MouseLeftButtonUp="Grid_MouseLeftButtonUp"
          Tag="dragdrop" />
    <Grid x:Name="DummyGrid" Grid.Row="1">
        <Grid x:Name="g2"
              Background="Blue"
              MouseLeftButtonDown="Grid_MouseLeftButtonDown"
              MouseLeftButtonUp="Grid_MouseLeftButtonUp"
              Tag="dragdrop" />
    </Grid>
</Grid>

答案 2 :(得分:1)

上次检查时,我的手机没有连接鼠标。

使用Tap事件代替MouseLeftButtonUp。对于更复杂的手势,请使用Silverlight Toolkit GestureListener类。

答案 3 :(得分:0)