WP7 отбрасывает MouseLeftButtonUp, если не получил ButtonDown - PullRequest
1 голос
/ 08 января 2012

Я пытаюсь получить элемент для запуска события 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 ]

2 голосов
/ 08 января 2012

Одним из способов решения этой проблемы является прослушивание TouchFrame для TouchAction.Up. Вам нужно рассчитать UIElement, которому ButtonUp соответствует, с помощью свойства Position TouchPoints, как описано здесь: http://forums.create.msdn.com/forums/p/98004/584465.aspx#584465

Другим способом является захват мыши в элементе ButtonDown UIElement. Это приведет к корректному срабатыванию ButtonUp, однако отправителем будет исходный UIElement, вызвавший ButtonDown. Вы можете отслеживать элементы, по которым движется мышь, используя MouseEnter и MouseLeave. Необходимость захвата мыши кратко затронута здесь: http://forums.create.msdn.com/forums/p/70785/431882.aspx

2 голосов
/ 08 января 2012

Мое решение немного похоже на ShawnFeatherly, но без TouchFrame.

По сути, как он говорит, если вы вызываете MouseCapture из сетки, где произошло событие MouseDown, 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. Тег - это универсальное поле, доступное для каждого элемента управления, которое вы можете использовать по своему усмотрению. Это особенно полезно для целей идентификации.

Начните с добавления его в сетку, которая вас интересует:

<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>
1 голос
/ 08 января 2012

В прошлый раз, когда я проверял, к моему телефону не была подключена мышь.

Используйте событие Tap вместо MouseLeftButtonUp. Для более сложных жестов используйте Silverlight Toolkit GestureListener class.

0 голосов
/ 01 февраля 2012
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...