Добавить событие клика в массив прямоугольников WPF

Мне нужно добавить событие клика в массив прямоугольников. Я использовал UniformGrid для хранения прямоугольников, и он динамический.

В XAML: <UniformGrid x:Name="GameUniformGrid" HorizontalAlignment="Left" Height="272" VerticalAlignment="Top" Width="272" Grid.Row="0" Grid.Column="0"/>

В C#:

for (int x = 0; x < rowcol; x++)
        {
            for (int y = 0; y < rowcol; y++)
            {
                rectangle[y, x] = new Rectangle { Stroke = Brushes.Black, StrokeThickness = 1, Fill = brush };
                GameUniformGrid.Children.Add(rectangle[y, x]);
            }
        }

3 ответа

Решение

Прямоугольник не имеет события щелчка. Однако у него есть события MouseDown и MouseUp. Вы можете определить событие MouseDown для своих прямоугольников в UniformGrid следующим образом:

<UniformGrid Rectangle.MouseDown="RectangleClickedEvent" ....../>

В коде позади вы можете иметь свой обработчик событий следующим образом:

 private void RectangleClicked(object sender, MouseButtonEventArgs e)
 {
    var clickedRectangle = e.Source as Rectangle ;
    //do something with rectangle. You already have the clicked rectangle here.
    //you can even search for this rectangle in your array now or whatever you want.
 }

Если вы хотите вместо этого использовать событие click, рассмотрите возможность использования Button, а не прямоугольника, и замените его шаблон элемента управления на прямоугольник. В этом случае вам придется использовать Button.Click вместо присоединенного свойства Rectangle.MouseDown в единой сетке.

<Button>
    <Button.Template>
        <ControlTemplate>
            <Rectangle Width="50" Height="50".../>
        </ControlTemplate>
    </Button.Template>
</Button> 

Однако я до сих пор не уверен, почему вы хотите хранить свои прямоугольники в массиве, поскольку вы всегда будете получать прямоугольник, по которому щелкнули... Пожалуйста, поделитесь тем, что вы пытаетесь сделать, чтобы кто-то мог предложить лучший подход,

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

Это один из способов реализовать вашу функциональность

(Я использую MVVM - так что никакой код позади и код не создают непосредственно элементы пользовательского интерфейса или устанавливают стиль)

  1. Добавьте ListView и установите единообразную сетку (или, возможно, Wrap Panel) в качестве ItempsPanelTemplate.
  2. Свяжите ViewModel с вашим представлением и добавьте наблюдаемую коллекцию, которая будет содержать ваши модели (т.е. дочерние /Rectangle-объекты), с помощью которых вы можете динамически добавлять или удалять элементы в коде, и он будет уведомлять представление об обновлении своего отображения.
  3. По вашему мнению, вы можете создать шаблон, который будет отображать каждую модель в виде прямоугольника или того, что вы когда-либо могли придумать.
  4. Наконец добавьте триггер, который будет уведомлять модель представления о том, что она выбрана.

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

Может быть, какой-то код может помочь:

  • здесь я использовал Студенты в качестве моделей - вы можете заменить их на класс Rectangles/Images/etc..
  • Я использую здесь UniformGrid, чтобы ответить на ваш вопрос, но я бы использовал здесь WrapPanel.

    <ListView
            HorizontalContentAlignment="Stretch"
            ItemsSource="{Binding Students}"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled"
            SelectedItem="{Binding SelectedStudent}">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid></UniformGrid>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Border>
                        <Grid>
                            <Grid.Style>
                                <Style>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="True">
                                            <Setter Property="Grid.Background" Value="#6DB4A0" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Grid.Style>
                            <TextBlock
                                Text="{Binding Name}" />
                        </Grid>
                    </Border>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    

Ваша ViewModel может быть что-то вроде

public class MainViewModel : ViewModelBase
{
    private Studetnt _student;

    public MainViewModel()
    {
        Students= new ObservableCollection<Student>(){};
    }

    public Student SelectedStudent
    {
        get { return _student; }
        set
        {
            if (_student != value && value != null)
            {
                _student= value;
            }
        }
    }

    public ObservableCollection<Student> Students{ get; set; }

}

Если вы новичок и не понимаете, что я сделал, то сначала я бы предложил вам прочитать о: MVVM/ Templates и Style в WPF/ ObservableCollections в WPF/ Triggers / Binding with RelativeSource В WPF.

Удачи:-)

Другие вопросы по тегам