Elad Yehuda
Member
- Joined
- Jul 3, 2023
- Messages
- 10
- Programming Experience
- 3-5
Hello everyone!
I'm writing code in WPF with a UserControl that builds a Sudoku board, so it can be used for any project that wants to add a Sudoku board. The idea I built is that the UserControl receives some kind of main interface that requires implementing special functions for the game itself, for example an interface that requires defining a special function that should actually return a two-dimensional array of int as the structure of a 9X9 Sudoku board given the difficulty level the function will receive. In addition, the interface requires implementing more testing functions in connection with the legality of the game.
Now the UserControl itself passes the instance of the interface to the ViewModel class which defines an ObservableCollection of a class I built that inherits directly from TextBox (which will actually contain all the slots on the panel) and in addition holds a property of a two-dimensional array of int that should store the two-dimensional array Dimension received from the function from the interface that returns the array of the game. The UserControl constructor calls a function that dynamically creates the board and in the process calls a special function that is in the ViewModel class to add the appropriate TextBox in the game board.
In addition, there is a special Convter of binding between the -Text property of the text box and the two-dimensional array according to the position, that is, when creating each text box using the row and col indexes, I transfer the indexes to the converter and return the corresponding value according to the requirement.
The code I presented works almost well for me, the only problem with it is that when there is a change in the text box, the converter activates the function ConvertBack - which should return a value according to the two-dimensional array at the index corresponding to that value - the frame of the text box is painted red and rightly so, because the set of the property of the two-dimensional array A dimension expects to receive a value corresponding to a characteristic that is a two-dimensional array and instead it receives a numerical value!
My question is how can I make the property of the two-dimensional array refer when it receives a numerical value to refer to the value to such a value that it should be put according to the appropriate index for it!? I haven't tried but I believe it is possible to return from the converter from the ConvertBack function an object that returns 3 elements the real value and the indexes to put the same value according to the appropriate indexes.
The problem with this is that because I'm actually implementing the set in the property, I'll commit to implementing the get of the property and this is where I get stuck because I can't return a value according to specific indexes!
I'm writing code in WPF with a UserControl that builds a Sudoku board, so it can be used for any project that wants to add a Sudoku board. The idea I built is that the UserControl receives some kind of main interface that requires implementing special functions for the game itself, for example an interface that requires defining a special function that should actually return a two-dimensional array of int as the structure of a 9X9 Sudoku board given the difficulty level the function will receive. In addition, the interface requires implementing more testing functions in connection with the legality of the game.
which looks like this::
// project UserControl
public interface IGameBoardProvider
{
int[,] GetBoard(string difficulty);
}
public interface IValidationGameBoardProvider
{
bool IsBoardValid(int value, int[] indexes);
int GetMoveValidInBorad(int row_or_col);
// List<int[]> GetIndexesLocationError(int[] indexes, int value);
}
public interface ICombinedGameBoardProvider : IGameBoardProvider, IValidationGameBoardProvider
{
}
public partial class UserControlBoardGame : UserControl
{
BoardViewModel viewModel;
public UserControlBoardGame(ICombinedGameBoardProvider boardGame, string level)
{
InitializeComponent();
viewModel = new BoardViewModel(boardGame, level);
GenerateBoard();
}
}
// project of WPF in MainWindow
// GameBoardProvider This is a class that inherits the interface ICombinedGameBoardProvider
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// GameBoardProvider This is a class that inherits the interface
UserControlBoardGame user = new UserControlBoardGame(new GameBoardProvider(), "Hard");
GridMain.Children.Add(user);
}
}
Now the UserControl itself passes the instance of the interface to the ViewModel class which defines an ObservableCollection of a class I built that inherits directly from TextBox (which will actually contain all the slots on the panel) and in addition holds a property of a two-dimensional array of int that should store the two-dimensional array Dimension received from the function from the interface that returns the array of the game. The UserControl constructor calls a function that dynamically creates the board and in the process calls a special function that is in the ViewModel class to add the appropriate TextBox in the game board.
In addition, there is a special Convter of binding between the -Text property of the text box and the two-dimensional array according to the position, that is, when creating each text box using the row and col indexes, I transfer the indexes to the converter and return the corresponding value according to the requirement.
which looks like this::
[AddINotifyPropertyChangedInterface]
// Model
public class TextBoxCell : TextBox
{ }
// ViewModel
[AddINotifyPropertyChangedInterface]
public class BoardViewModel
{
public int[,] Board
{
get;
set;
}
private ICombinedGameBoardProvider gameBorad;
public ObservableCollection<TextBoxCell> TextBoxCells { get; set; }
public BoardViewModel(ICombinedGameBoardProvider gameBorad, string level)
{
this.gameBorad = gameBorad;
TextBoxCells = new ObservableCollection<TextBoxCell>();
GameNew(level);
}
public void GameNew(string level)
{
board = this.gameBorad.GetBoard(level);
}
public void GenerateTextBoxCell(int[] indexesCell)
{
var textBox = new TextBoxCell();
Func<IValueConverter, Binding> createBinding = (convter) =>
{
Binding bind = new Binding("Board")
{
Source = this,
Converter = convter,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
};
return bind;
};
textBox.SetBinding(TextBox.TextProperty, createBinding(new CellTextConverter(indexesCell)));
}
}
//Converter
public class CellTextConverter : IValueConverter
{
int row, col;
public CellTextConverter(int[] indexes)
{
this.row = indexes[0];
this.col = indexes[1];
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int[,] arr = (int[,])value;
string cellValue = arr[row, col].ToString();
return cellValue != "0" ? cellValue : "";
}
//not work well
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString() != "" ? int.Parse(value.ToString()) : 0;
}
}
The code I presented works almost well for me, the only problem with it is that when there is a change in the text box, the converter activates the function ConvertBack - which should return a value according to the two-dimensional array at the index corresponding to that value - the frame of the text box is painted red and rightly so, because the set of the property of the two-dimensional array A dimension expects to receive a value corresponding to a characteristic that is a two-dimensional array and instead it receives a numerical value!
My question is how can I make the property of the two-dimensional array refer when it receives a numerical value to refer to the value to such a value that it should be put according to the appropriate index for it!? I haven't tried but I believe it is possible to return from the converter from the ConvertBack function an object that returns 3 elements the real value and the indexes to put the same value according to the appropriate indexes.
The problem with this is that because I'm actually implementing the set in the property, I'll commit to implementing the get of the property and this is where I get stuck because I can't return a value according to specific indexes!