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($"_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);
}
}
}
}
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:
<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>
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);
}
}
}
}
In your .cs file,
You define two different
ChessViewModelinstance. One is for BindingContext. Another is useless. Then you create a newChessboardViewinstance. 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:
Hope it helps!