Хит Тест поведения - PullRequest
       4

Хит Тест поведения

2 голосов
/ 01 декабря 2010

У меня есть следующий код

public partial class MainWindow : Window
{
    public MainWindow() {
        InitializeComponent();
    }

    List<UIElement> ucs = new List<UIElement>();

    private void Window_PreviewMouseLeftButtonDown(object sender,
        MouseButtonEventArgs e)
    {
        ucs.Clear();

        Point p = e.GetPosition((UIElement)sender);

        VisualTreeHelper.HitTest(this, null,
            new HitTestResultCallback(MyHitTestCallback),
            new PointHitTestParameters(p));

        Console.WriteLine("ucs.Count = {0}", ucs.Count);

        foreach (var item in ucs)
        {
            Console.WriteLine("item: {0}", item.ToString());
        }
    }

    HitTestResultBehavior MyHitTestCallback(HitTestResult result)
    {
        ucs.Add(result.VisualHit as UIElement);
        return HitTestResultBehavior.Continue;
    }
}

это мое окно

<Window>
    <Grid>
        <my:UserControl1 HorizontalAlignment="Left" Margin="82,88,0,0" x:Name="userControl11" VerticalAlignment="Top" />
        <my:UserControl1 HorizontalAlignment="Left" Margin="168,166,0,0" x:Name="userControl12" VerticalAlignment="Top" />
        <my:UserControl1 HorizontalAlignment="Left" Margin="231,130,0,0" x:Name="userControl13" VerticalAlignment="Top" />
    </Grid>
</Window>

это мой UC

<UserControl>
    <Grid>
        <Label Content="Label" Height="44" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" FontSize="20" FontWeight="Bold" Width="78" Background="#FF4B9FC4" BorderBrush="#FF020A0D" BorderThickness="1" />
    </Grid>
</UserControl>

это вывод при нажатииНА КОНТРОЛЕ ПОЛЬЗОВАТЕЛЯ, затем на пересечении 2 пользовательских элементов управления:

ucs.Count = 2
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
ucs.Count = 3
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border

Почему это?Где находится UserControl под экземпляром мыши?

PS:
Теперь, когда у меня на ярлыке есть BorderThickness = 0

ucs.Count = 3
item: System.Windows.Controls.TextBlock
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
ucs.Count = 3
item: System.Windows.Controls.TextBlock
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border

1 Ответ

2 голосов
/ 01 декабря 2010

UserControl1 невидим. Его содержимое является видимым, но сам экземпляр UserControl1 не имеет собственных визуальных элементов. (И этого никогда не будет. Работа пользовательского элемента управления на самом деле состоит только в том, чтобы содержать другие вещи.)

Тестирование попаданий только сообщает о элементах, которые вносят прямой вклад в визуальное дерево. И поскольку тестирование попаданий рассматривает каждый элемент изолированно, это означает, что элементы, которые действуют исключительно как контейнеры, не отображаются. (И связанный с этим факт заключается в том, что тестирование попаданий учитывает только те пиксели, которые действительно были окрашены. Поэтому, если у вас есть Border, где вы установили BorderBrush и ненулевое BorderThickness, но у вас нет Background тест на попадание будет считать только контур границы хитом - точки внутри границы не будут считаться попаданием на границу, потому что в его интерьере ничего не нарисовано.

Если вам нужно выполнить проверку на удар в стиле "эта вещь или что-то внутри этой вещи", то либо либо

  1. использовать события ввода / вывода с помощью мыши - эти пузырьки, и они будут подниматься даже на невидимых элементах контейнера
  2. используйте IsMouseOver или
  3. используйте используемую вами функцию проверки попадания, передавая пользовательский элемент управления в качестве первого аргумента, и обрабатывайте любое попадание как признак того, что точка проверки попадания находится внутри пользовательского элемента управления

Третий - более сложный, но если вам нужно набрать контрольные точки, отличные от тех, которые в данный момент находятся под мышью, вам нужно будет их использовать.

...