создать доску для игры с поддержкой событий в WPF - PullRequest
2 голосов
/ 02 апреля 2010

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

Моей первой идеей была Грид. Я делаю это в коде позади, но вредно реализовывать события или все во время выполнения create board: /

        int size = 12;
        Grid board = new Grid();
        board.ShowGridLines = true;
        for (int i = 0; i < size;i++ )
        {
            board.ColumnDefinitions.Add(new ColumnDefinition());
            board.RowDefinitions.Add(new RowDefinition());
        }

        //komputer
        Rectangle ai = new  Rectangle();
        ai.Height = 20;
        ai.Width = 20;
        ai.AllowDrop = true;
        ai.Fill = Brushes.Orange;
        Grid.SetRow(ai, 0);
        Grid.SetColumn(ai,0);
        //człowiek
        Rectangle hum = new Rectangle();
        hum.Height = 20;
        hum.Width = 20;
        hum.AllowDrop = true;
        hum.Fill = Brushes.Green;
        Grid.SetRow(hum,size);
        Grid.SetColumn(hum,size);
        board.Children.Add(ai);
        board.Children.Add(hum);
        this.Content = board;
  • Это способ динамически менять столбцы и строки в XAML?
  • Это лучший способ реализовать эту доску для создания и реализации событий при перемещении пешки из одной ячейки в другую?

1 Ответ

2 голосов
/ 03 апреля 2010

Вам все равно придется использовать выделенный код для изменения свойств RowDefinitions и ColumnDefinitions Grid в этом примере, поскольку они не являются свойствами зависимости. Но вся остальная логика может быть обработана в классе модели представления.

XAML:

<Window x:Class="GameBoard.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:GameBoard="clr-namespace:GameBoard"
        Title="Window1"
        SizeToContent="WidthAndHeight">
    <Grid Margin="50">
        <Grid.Resources>

            <!-- This template presents the Piece object.  Note that you can't set
                 the Grid.Row and Grid.Column properties on this Rectangle - well,
                 you *can*, but the Grid won't see them.  See the Style below.  -->
            <DataTemplate DataType="{x:Type GameBoard:Piece}">
                <Rectangle Fill="{Binding Fill}"
                           Width="50"
                           Height="50" />
            </DataTemplate>

            <!-- When the ItemsControl creates its items, it wraps each item in a
                 ContentPresenter.  You have to set Grid.Row and Grid.Column
                 on this ContentPresenter in order for the Grid to see them. -->
            <Style TargetType="{x:Type ContentPresenter}">
                <Setter Property="Grid.Row"
                        Value="{Binding Row}" />
                <Setter Property="Grid.Column"
                        Value="{Binding Column}" />
            </Style>

        </Grid.Resources>
        <Border BorderBrush="Black"
                BorderThickness="1">
            <ItemsControl x:Name="Board"
                          ItemsSource="{Binding}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                                <RowDefinition Height="50" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="50" />
                            </Grid.ColumnDefinitions>
                        </Grid>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </Border>
    </Grid>
</Window>

Класс Piece - очевидно, вам потребуется реализовать INotifyPropertyChanged в свойствах Row и Column для обработки движущихся частей вокруг.

public class Piece
{
    public int Column { get; set; }
    public Brush Fill { get; set; }
    public int Row { get; set; }
}

Заполнение доски:

    public Window1()
    {
        InitializeComponent();

        ObservableCollection<Piece> pieces = new ObservableCollection<Piece>();
        pieces.Add(
            new Piece {Row = 0, Column = 0, Fill = new SolidColorBrush(Colors.BlanchedAlmond)});
        pieces.Add(
            new Piece {Row = 7, Column = 7, Fill = new SolidColorBrush(Colors.RosyBrown)});
        pieces.Add(
            new Piece { Row = 3, Column = 4, Fill = new SolidColorBrush(Colors.BlueViolet) });
        pieces.Add(
            new Piece { Row = 5, Column = 4, Fill = new SolidColorBrush(Colors.Orange) });

        Board.DataContext = pieces;
    }

Я использовал ItemsControl, чтобы содержать кусочки в этом примере. Вместо этого вы могли бы использовать ListBox - это хорошо, потому что он дает вам выбор предметов бесплатно. Обратите внимание, что если вы сделаете это, вам придется изменить Style TargetType на ListBoxItem, поскольку именно в него ListBox оборачивает свои элементы item вместо ContentPresenter.

Edit:

Я написал этот ответ довольно давно, и у него есть проблема.

Назначение свойств Grid.Row и Grid.Column с использованием стиля, применяемого к контейнеру элементов, сгенерированному сеткой, является правильным. Выяснить, что контейнер элемента является ContentPresenter, а создать стиль по умолчанию для этого типа - нет. (В этом случае он будет работать надежно, но во многих случаях это не работает.)

Вы все равно должны создать стиль, но он должен быть назначен на ItemsControl ItemContainerStyle. Этот стиль автоматически применяется к любому элементу контейнера, который элемент управления генерирует для своих элементов - поэтому, если ItemsControl вы используете ListBox, он применяет его к ListBoxItem, а если TabControl, то он Применится к TabItem и т. д.

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