在屏幕上显示图像按钮。

huangapple go评论69阅读模式
英文:

Displaying imagebuttons on screen

问题

我正在尝试使用Xamarin.Forms在C#中创建一个国际象棋应用程序。现在我正在尝试实现突出显示和移动棋子的功能。我编写了一段代码,应该在点击一个棋子时显示每个可能的移动,显示为可点击的图像按钮(点击这些按钮将使移动),但是它没有发生,我真的不确定为什么。

这是我认为需要理解我的问题的代码:

protected virtual void OnPieceClicked(object sender, EventArgs e)
{
    var pieceButton = (ImageButton)sender;

    //debug
    Console.WriteLine($"_chessboardView is null: {_chessboardView == null}");
    if (_chessboardView != null)
    {
        Console.WriteLine($"_possibleMoveButtons is null: {_chessboardView._possibleMoveButtons == null}");
    }

    Piece clickedPiece = null;
    for (int row = 0; row < 8; row++)
    {
        for (int col = 0; col < 8; col++)
        {
            Piece piece = _chessBoard.Board[row, col];
            if (piece != null && piece.PieceButton == pieceButton)
            {
                clickedPiece = piece;
                _currentRow = row;
                _currentCol = col;
                break;
            }
        }
        if (clickedPiece != null)
        {
            break;
        }
    }

    var possibleMoves = GetPossibleMoves(_currentRow, _currentCol, _chessBoard.Board);

    //debug
    Console.WriteLine($"Number of possible moves for clicked piece: {possibleMoves.Count}");

    foreach (var move in possibleMoves)
    {
        var moveButton = new ImageButton
        {
            Source = "possible_move", // TODO: change pic
            BackgroundColor = Color.Red,
            CommandParameter = move
        };
        moveButton.Clicked += OnMoveClicked;

        _chessboardView._possibleMoveButtons.Add(moveButton);
        _chessboardView._moveButtons.Add(moveButton);
        _chessboardView.Children.Add(moveButton, move.col, move.row);

        //debug
        Console.WriteLine($"Added move button at row {move.row}, col {move.col}");
    }
}
public void UpdateBoard()
{
    // Remove previous piece images from the board
    foreach (ImageButton pieceButton in _pieceButtons)
    {
        Children.Remove(pieceButton);
    }
    foreach (ImageButton moveButton in _moveButtons)
    {
        Children.Remove(moveButton);
    }
    foreach (ImageButton possibleMoveButton in _possibleMoveButtons)
    {
        Children.Remove(possibleMoveButton);
    }

    _possibleMoveButtons.Clear();
    _moveButtons.Clear();
    _pieceButtons.Clear();

    //debug
    if (_chessBoard == null)
    {
        System.Diagnostics.Debug.WriteLine("ChessBoard is null");
        return;
    }

    if (_chessBoard.Board == null)
    {
        System.Diagnostics.Debug.WriteLine("ChessBoard's Board is null");
        return;
    }

    for (int row = 0; row < 8; row++)
    {
        for (int col = 0; col < 8; col++)
        {
            Piece piece = _chessBoard.Board[col, row];
            if (piece != null)
            {
                ImageButton pieceButton = piece.PieceButton;

                _pieceButtons.Add(pieceButton);
                Children.Add(pieceButton, col, row);
            }
        }
    }
}

我尝试在代码中放置断点以查看代码是否运行正确,似乎代码运行正确,只是图像没有显示在国际象棋棋盘上。我真的不知道该怎么办。非常感谢您提前的帮助!

编辑:我还添加了XAML代码以及生成国际象棋棋盘的方法,如果有帮助的话:

<StackLayout>
    <local:ChessboardView x:Name="szachownica"
              ChessBoard="{Binding CurrentChessBoard}"
              RowSpacing="0" ColumnSpacing="0"
              Margin="20"
              HeightRequest="{Binding Path=Width, Source={x:Reference szachownica}}"
              InputTransparent="False">
        
    </local:ChessboardView>
    <Button Text="Previous move" Command="{Binding UndoMoveCommand}" />
    <Button Text="New Game" Command="{Binding NewGameCommand}" />
    <Button Text="New Game (vs AI)" Command="{Binding NewGameAICommand}" />
    <Button Text="New Game 960" Command="{Binding NewGame960Command}" />
</StackLayout>
</ContentPage>
public ChessboardView()
{
    _possibleMoveButtons = new List<ImageButton>();

    for (int i = 0; i < 8; i++)
    {
        RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
        ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
    }

    for (int row = 0; row < 8; row++)
    {
        for (int col = 0; col < 8; col++)
        {
            BoxView square = new BoxView
            {
                BackgroundColor = (row + col) % 2 == 0 ? Color.White : Color.Gray
            };

            Children.Add(square, col, row);
        }
    }
}
public ChessBoard()
{
    Board = new Piece[8, 8];
    InitializeBoard();
    
    for (int x = 0; x < 8; x++)
    {
        for (int y = 0; y < 8; y++)
        {
            Piece piece = Board[x, y];
            if (piece != null)
            {
                piece.SetChessBoardAndChessboardView(this, _chessboardView);
            }
        }
    }
}
英文:

I am trying to create a chess app in C# using Xamarin.Forms. Right now I am trying to implement the functionality of highlighting and moving pieces. I made code which should display every possible move upon clicking a piece as a clickable image button (clicking those buttons would make the move) however it does not happen and I am really not sure why.
This is the code which I think is necessary to understand my problem:

protected virtual void OnPieceClicked(object sender, EventArgs e)
    {
        var pieceButton = (ImageButton)sender;

            //debug
            Console.WriteLine($&quot;_chessboardView is null: {_chessboardView == null}&quot;);
            if (_chessboardView != null)
            {
                Console.WriteLine($&quot;_possibleMoveButtons is null: {_chessboardView._possibleMoveButtons == null}&quot;);
            }

            Piece clickedPiece = null;
         for (int row = 0; row &lt; 8; row++)
        {
            for (int col = 0; col &lt; 8; col++)
            {
                Piece piece = _chessBoard.Board[row, col];
                if (piece != null &amp;&amp; piece.PieceButton == pieceButton)
                {
                    clickedPiece = piece;
                    _currentRow = row;
                    _currentCol = col;
                    break;
                }
            }
            if (clickedPiece != null)
            {
                break;
            }
        }
        
        var possibleMoves = GetPossibleMoves(_currentRow, _currentCol, _chessBoard.Board);

            //debug
            Console.WriteLine($&quot;Number of possible moves for clicked piece: {possibleMoves.Count}&quot;);

        foreach (var move in possibleMoves)
        {
            var moveButton = new ImageButton
            {
                Source = &quot;possible_move&quot;, // TODO: change pic
                BackgroundColor = Color.Red,
                CommandParameter = move
            };
            moveButton.Clicked += OnMoveClicked;

                _chessboardView._possibleMoveButtons.Add(moveButton);
            _chessboardView._moveButtons.Add(moveButton);
            _chessboardView.Children.Add(moveButton, move.col, move.row);

                //debug
                Console.WriteLine($&quot;Added move button at row {move.row}, col {move.col}&quot;);
        }
    }
public void UpdateBoard()
        {
            // Remove previous piece images from the board
            foreach (ImageButton pieceButton in _pieceButtons)
            {
                Children.Remove(pieceButton);
            }
            foreach (ImageButton moveButton in _moveButtons)
            {
                Children.Remove(moveButton);
            }
            foreach (ImageButton possibleMoveButton in _possibleMoveButtons)
            {
                Children.Remove(possibleMoveButton);
            }

            _possibleMoveButtons.Clear();
            _moveButtons.Clear();
            _pieceButtons.Clear();

            //debug
            if (_chessBoard == null)
            {
                System.Diagnostics.Debug.WriteLine(&quot;ChessBoard is null&quot;);
                return;
            }

            if (_chessBoard.Board == null)
            {
                System.Diagnostics.Debug.WriteLine(&quot;ChessBoard&#39;s Board is null&quot;);
                return;
            }

            for (int row = 0; row &lt; 8; row++)
            {
                for (int col = 0; col &lt; 8; col++)
                {
                    Piece piece = _chessBoard.Board[col, row];
                    if (piece != null)
                    {
                        ImageButton pieceButton = piece.PieceButton;

                        _pieceButtons.Add(pieceButton);
                        Children.Add(pieceButton, col, row);
                    }
                }
            }
        }

I tried placing breakpoints in the code to see if the code even runs and it seems that it runs correctly, it's just the images don't display on the chessboard.
I really don't know what to do here. Thank you so much for your help in advance!

EDIT: I'm also adding xaml code and the methods for generating my chessboard if that's helpful:

&lt;StackLayout&gt;
    &lt;local:ChessboardView x:Name=&quot;szachownica&quot;
              ChessBoard=&quot;{Binding CurrentChessBoard}&quot;
              RowSpacing=&quot;0&quot; ColumnSpacing=&quot;0&quot;
              Margin=&quot;20&quot;
              HeightRequest=&quot;{Binding Path=Width, Source={x:Reference szachownica}}&quot;
              InputTransparent=&quot;False&quot;&gt;
        
    &lt;/local:ChessboardView&gt;
    &lt;Button Text=&quot;Previous move&quot; Command=&quot;{Binding UndoMoveCommand}&quot; /&gt;
    &lt;Button Text=&quot;New Game&quot; Command=&quot;{Binding NewGameCommand}&quot; /&gt;
    &lt;Button Text=&quot;New Game (vs AI)&quot; Command=&quot;{Binding NewGameAICommand}&quot; /&gt;
    &lt;Button Text=&quot;New Game 960&quot; Command=&quot;{Binding NewGame960Command}&quot; /&gt;
&lt;/StackLayout&gt;

</ContentPage>

public ChessboardView()
    {
        _possibleMoveButtons = new List&lt;ImageButton&gt;();

        for (int i = 0; i &lt; 8; i++)
        {
            RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        }

        for (int row = 0; row &lt; 8; row++)
        {
            for (int col = 0; col &lt; 8; col++)
            {
                BoxView square = new BoxView
                {
                    BackgroundColor = (row + col) % 2 == 0 ? Color.White : Color.Gray
                };

                Children.Add(square, col, row);
            }
        }
    }
    public ChessBoard()
        {
            Board = new Piece[8, 8];
            InitializeBoard();
            
            for (int x = 0; x &lt; 8; x++)
            {
                for (int y = 0; y &lt; 8; y++)
                
                {
                    Piece piece = Board[x, y];
                    if (piece != null)
                    {
                        piece.SetChessBoardAndChessboardView(this, _chessboardView);
                    }
                }
            }
        }

</details>


# 答案1
**得分**: 0

在你的 .cs 文件中,

```csharp
public MainPage()
{
    InitializeComponent();
    this.BindingContext = new ChessViewModel();

    var viewModel = new ChessViewModel();
    var chessboardView = new ChessboardView();
    chessBoard = new ChessBoard(chessboardView);
    viewModel.ChessboardView = chessboardView;
    viewModel.CurrentChessBoard = chessBoard;
}

你定义了两个不同的 ChessViewModel 实例。一个用于 BindingContext,另一个没有用。然后你创建了一个新的 ChessboardView 实例。这不同于在 xaml 中命名为 "szachownica" 的那个。所以图片按钮不会显示在 "szachownica" 上。

你可以像下面这样更改 .cs 文件:

public partial class MainPage : ContentPage
{
    ChessViewModel viewModel;
    private ChessBoard chessBoard;
    public MainPage()
    {
        InitializeComponent();
        viewModel = new ChessViewModel();
        this.BindingContext = viewModel;

        chessBoard = new ChessBoard(this.szachownica);
        viewModel.ChessboardView = this.szachownica;
        viewModel.CurrentChessBoard = chessBoard;
    }
}

希望对你有所帮助!

英文:

In your .cs file,

    public MainPage()
    {
        InitializeComponent();
        this.BindingContext = new ChessViewModel();

        var viewModel = new ChessViewModel();
        var chessboardView = new ChessboardView();
        chessBoard = new ChessBoard(chessboardView);
        viewModel.ChessboardView = chessboardView;
        viewModel.CurrentChessBoard = chessBoard;
    }

You define two different ChessViewModel instance. One is for BindingContext. Another is useless. Then you create a new ChessboardView instance. That's not the same as the one (named "szachownica") in xaml. So the imagebutton will not show on "szachownica".

You may change the .cs file like the following:

public partial class MainPage : ContentPage
{
    ChessViewModel viewModel;
    private ChessBoard chessBoard;
    public MainPage()
    {
        InitializeComponent();
        viewModel = new ChessViewModel();
        this.BindingContext = viewModel;

        chessBoard = new ChessBoard(this.szachownica);
        viewModel.ChessboardView = this.szachownica;
        viewModel.CurrentChessBoard = chessBoard;
    }
}

Hope it helps!

huangapple
  • 本文由 发表于 2023年6月22日 17:41:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定