c# - WPF 中的数独 - 我应该为表格使用什么基本元素?

标签 c# wpf data-binding mvvm-light

我用 C#、XAML 和 MVVM-Light 构建了一个非常基本的数独应用程序。 MainWindow 每个单元格有一个 9x9 网格和 81 个文本框,MainViewModel 有 81 个 int 属性。不漂亮。数独表格看起来不像经典表格,没有“较粗的边框”来区分每个象限。

现在,我想进入下一个阶段,让它变得漂亮又实用。

每个单元格内容都必须是“响应式”的?即根据窗口的宽度/高度调整大小(字体大小)。我已经开始研究处理字体颜色、背景颜色等的 CellUserControl。

主窗口的基础应该是什么?网格、表格、列表框、自定义?

  • 我尝试过网格和表格,但通常都会陷入死胡同。 XAML 变得非常冗长且重复。
  • 我记得 MS 展示了 WPF 的强大功能,只需应用样式即可将 ListBox 显示为轮播。这是有效路径吗?
  • 自定义控件:它是否太过分了,或者它的存在正是为了这种情况?

顺便说一句,我将大量利用 MVVM-Light 和数据绑定(bind)。

最佳答案

由于所有单元格应具有相同的大小,因此您也可以使用 UniformGrid 。正如 Leo Bartkus 所建议的,您可以使用隐藏代码来生成单元格和文本框。为此,首先在 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;
    }
}

嵌套循环为 81 个单元格创建每个 BorderTextBox。边框的厚度是根据当前单元格的位置确定的。这将为您提供典型的数独表格外观。

文本框数据绑定(bind)到 View 模型的二维索引器属性。这是 View 模型:

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 .

关于c# - WPF 中的数独 - 我应该为表格使用什么基本元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54055388/

相关文章:

c# - 无法绑定(bind)到实现 ICollection<T> 的对象的属性

c# - 如何从它绑定(bind)到的 DataRow 中确定 DataGridViewRow

c# - 我可以通过 DataTrigger (XAML) 调用函数吗?

wpf - MSIX 使用 Azure SSO 的已安装 WPF 应用程序将无法启动

C# : catch all errors/exceptions of a mixed managed/unmanaged process

asp.net - 在 asp 的 gridview 中使用 eval 获取 this 对象

c# - 数据绑定(bind)到嵌套属性?

c# - 监控 C# 线程 - 哪个做什么/什么时候

c# - RSACryptoServiceProvider 在 .net 核心中不工作

c# - 使用 SortedDictionary - 获取下一个值