Тестирование попаданий с новыми UIElements

Я создаю пользовательский элемент управления WPF, который должен проверять, не пересекаются ли новые UIElement с существующими UIElements. Приведенный ниже код отлично работает, когда baseRectangle добавляется на холст перед вызовом button1_Click, но если прямоугольник добавляется в методе button1_Click, проверка попадания не работает.

<Window x:Class="WpfCollisionTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas Height="246" HorizontalAlignment="Left" Margin="12,12,0,0" Name="canvas1" VerticalAlignment="Top" Width="479"></Canvas>
        <Button Content="Button" Height="35" HorizontalAlignment="Left" Margin="12,264,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>


 public MainWindow()
 { 
     InitializeComponent();
 }

 private void button1_Click(object sender, RoutedEventArgs e)
 {
     canvas1.Children.Clear();
     Rectangle rect = new Rectangle();
     rect.Width = 200;
     rect.Height = 200;
     rect.Fill = Brushes.Red;
     canvas1.Children.Add(rect);
     if (VisualTreeHelper.HitTest(canvas1, new Point(100, 100)) != null)
     {
         MessageBox.Show("Collision");
     }
 }

person Jargo    schedule 30.01.2012    source источник
comment
Элемент управления должен быть отрендерен, прежде чем вы сможете проверить его на нажатие. Возможно, запустите проверку попадания с более низким приоритетом диспетчера, чем Render.   -  person Rachel    schedule 30.01.2012
comment
Проблема с этим подходом заключается в том, что мне нужно добавить десятки объектов, требующих проверки на попадание. Есть ли способ выполнить проверку вручную перед рендерингом? Мне нужно сделать хиттесты против группы TextBlocks, которые у меня есть в отдельной коллекции, если это поможет.   -  person Jargo    schedule 30.01.2012
comment
Не проверив это: попробуйте добавить canvas1.UpdateLayout(); непосредственно перед кодом проверки попадания. Это просто предположение.   -  person Clemens    schedule 30.01.2012
comment
Спасибо, Клеменс. Ваше решение сработало.   -  person Jargo    schedule 01.02.2012


Ответы (2)


Вызов canvas1.UpdateLayout() до того, как проблема будет решена.

person Jargo    schedule 01.02.2012

Попробуйте добавить это после добавления прямоугольника на холст:

canvas1.Children.Add(rect);
rect.LayoutUpdated += (s, args) =>
{
    if (VisualTreeHelper.HitTest(canvas1, new Point(100, 100)) != null)
    {
        MessageBox.Show("Collision");
    }
};

Конечно, это будет срабатывать каждый раз, когда обновляется макет прямоугольника... поэтому вы можете удалить обработчик или выполнить дополнительную проверку внутри него.

person Paul Hoenecke    schedule 30.01.2012