Поскольку все ячейки должны иметь одинаковый размер, вы также можете использовать UniformGrid . Как предположил Лео Барткус, вы можете использовать выделенный код для генерации ячеек и текстовых полей. Для этого начните с создания заполнителя для таблицы Судоку в XAML:
<!-- Placeholder for Sudoku table (filled in code-behind) -->
<Border x:Name="SudokuTable" />
Предполагая, что вы используете Window
, вот код:
public partial class MainWindow : Window
{
private const int InnerWidth = 3;
private const int OuterWidth = InnerWidth * InnerWidth;
private const int Thin = 1;
private const int Thick = 3;
public MainWindow()
{
InitializeComponent();
InitializeViewModel();
InitializeSudokuTable();
}
public SudokuViewModel ViewModel => (SudokuViewModel)DataContext;
private void InitializeViewModel()
{
DataContext = new SudokuViewModel(OuterWidth);
}
private void InitializeSudokuTable()
{
var grid = new UniformGrid
{
Rows = OuterWidth,
Columns = OuterWidth
};
for (var i = 0; i < OuterWidth; i++)
{
for (var j = 0; j < OuterWidth; j++)
{
var border = CreateBorder(i, j);
border.Child = CreateTextBox(i, j);
grid.Children.Add(border);
}
}
SudokuTable.Child = grid;
}
private static Border CreateBorder(int i, int j)
{
var left = j % InnerWidth == 0 ? Thick : Thin;
var top = i % InnerWidth == 0 ? Thick : Thin;
var right = j == OuterWidth - 1 ? Thick : 0;
var bottom = i == OuterWidth - 1 ? Thick : 0;
return new Border
{
BorderThickness = new Thickness(left, top, right, bottom),
BorderBrush = Brushes.Black
};
}
private TextBox CreateTextBox(int i, int j)
{
var textBox = new TextBox
{
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
var binding = new Binding
{
Source = ViewModel,
Path = new PropertyPath($"[{i},{j}]"),
Mode = BindingMode.TwoWay
};
textBox.SetBinding(TextBox.TextProperty, binding);
return textBox;
}
}
Вложенный цикл создает каждый Border
и TextBox
для 81 ячейки. Толщины границ определяются на основе текущего положения ячейки. Это даст вам типичный вид стола Судоку.
Текстовые поля привязаны к данным для свойства двумерного индексатора модели представления. Вот вид модели:
public class SudokuViewModel : ViewModelBase
{
private readonly string[,] _values;
public SudokuViewModel(int width)
{
_values = new string[width, width];
}
public string this[int i, int j]
{
get => _values[i, j];
set => Set(ref _values[i, j], value);
}
}
Этот индексатор возвращает строку, но вы можете изменить ее на целое число и выполнить соответствующие преобразования и проверки ошибок. В любом случае он использует MVVM Light для вызова события PropertyChanged
при обновлении свойства индексатора.
Я создал хранилище с моим решением здесь: https://github.com/redcurry/Sudoku.