【问题标题】:C# string array element not updatingC# 字符串数组元素不更新
【发布时间】:2021-01-11 14:38:29
【问题描述】:

我正在学习 Blazor 以使用 C# 创建 Web 应用程序。应用程序中的页面之一是拼字游戏。我的实现细节如下:

  • 一个 Board 类,存储其大小(默认为 15)和高级方格(双字、双字母等)。 Scrabble 类实现 UI 创建、操作、数据绑定等...
  • 一个新的 Board 实例初始化所有方形类型(高级和非高级)
  • Scrabble 类有一个 Init 方法,该方法查看每个方块的 Board 成员,然后将相应的颜色代码存储在 string 2D array(与板相同大小,便于访问)。 这个数组后面就是我说的问题
  • UI 使用具有 15 行的 HTML 表格显示板,每行有 15 个单元格,其 style 属性使用 Blazor 的特殊语法 @ 与上述字符串数组的相应颜色代码绑定。每个单元格还实现了一个 onclick 回调,为简单起见,我只是将第一个单元格的颜色(第 0 行第 0 行)更改为被点击单元格的颜色

问题:

  • (0, 0) 处的 HTML 单元格不会改变其颜色。起初我认为这是由于绑定问题(也许我使用了错误的语法)。因此,我尝试将此单元格专门绑定到一个单独的字符串成员,并且效果很好。 结论:不是绑定问题
  • 这次我在更新字符串数组中的元素之前和之后添加了一些控制台打印,以查看更改是否生效,我发现了问题。打印显示该元素确实已正确更新,但是一旦回调方法完成,更改将恢复,并且 HTML 单元格的颜色保持不变。这可以通过再次单击来确认(在任何单元格上,因为它调用相同的回调方法),打印显示颜色代码 before 更新与 after 不同之前的打印,但与 before 相同。具体来说,打印是:Click #1: (before) red (after) blue. Click #2: (before) red (after) blue click #2 的 before 应该是蓝色的

解决方法:

  • 尝试将字符串数组从 2D 更改为 1D,同样的问题
  • 尝试使用List<string>,它可以工作。所以我现在坚持使用 List,但我仍然更喜欢数组,因为 2D 索引访问语法比使用 list[15 * row + col]list[row][col](嵌套列表)更简洁

问题:为什么?为什么阵列不能按预期工作?显然它在退出方法之前更新但之后又恢复了

代码:

Board.cs

public class Board
{
    public enum SquareKind
    {
        White,
        DL,
        TL,
        DW,
        TW,
        Start
    }
    public const int SIZE = 15;
    public readonly (int row, int col) StartPos = (7, 7);
    public SquareKind[,] Squares = new SquareKind[SIZE, SIZE];

    public Board()
    {
        // Initialize premium squares (including starting one)
        Squares[0, 0] = SquareKind.TW;
        Squares[1, 5] = SquareKind.TL;
        Squares[5, 1] = SquareKind.TL;
        Squares[5, 5] = SquareKind.TL;
        Squares[1, 1] = SquareKind.DW;
        Squares[2, 2] = SquareKind.DW;
        Squares[3, 3] = SquareKind.DW;
        Squares[4, 4] = SquareKind.DW;
        Squares[0, 3] = SquareKind.DL;
        Squares[3, 0] = SquareKind.DL;
        Squares[2, 6] = SquareKind.DL;
        Squares[6, 2] = SquareKind.DL;
        Squares[6, 6] = SquareKind.DL;
        Squares[0, 14] = SquareKind.TW;
        Squares[1, 9] = SquareKind.TL;
        Squares[5, 13] = SquareKind.TL;
        Squares[5, 9] = SquareKind.TL;
        Squares[1, 13] = SquareKind.DW;
        Squares[2, 12] = SquareKind.DW;
        Squares[3, 11] = SquareKind.DW;
        Squares[4, 10] = SquareKind.DW;
        Squares[0, 11] = SquareKind.DL;
        Squares[3, 14] = SquareKind.DL;
        Squares[2, 8] = SquareKind.DL;
        Squares[6, 12] = SquareKind.DL;
        Squares[6, 8] = SquareKind.DL;
        Squares[14, 14] = SquareKind.TW;
        Squares[13, 9] = SquareKind.TL;
        Squares[9, 13] = SquareKind.TL;
        Squares[9, 9] = SquareKind.TL;
        Squares[13, 13] = SquareKind.DW;
        Squares[12, 12] = SquareKind.DW;
        Squares[11, 11] = SquareKind.DW;
        Squares[10, 10] = SquareKind.DW;
        Squares[14, 11] = SquareKind.DL;
        Squares[11, 14] = SquareKind.DL;
        Squares[12, 8] = SquareKind.DL;
        Squares[8, 12] = SquareKind.DL;
        Squares[8, 8] = SquareKind.DL;
        Squares[14, 0] = SquareKind.TW;
        Squares[13, 5] = SquareKind.TL;
        Squares[9, 1] = SquareKind.TL;
        Squares[9, 5] = SquareKind.TL;
        Squares[13, 1] = SquareKind.DW;
        Squares[12, 2] = SquareKind.DW;
        Squares[11, 3] = SquareKind.DW;
        Squares[10, 4] = SquareKind.DW;
        Squares[14, 3] = SquareKind.DL;
        Squares[11, 0] = SquareKind.DL;
        Squares[12, 6] = SquareKind.DL;
        Squares[8, 2] = SquareKind.DL;
        Squares[8, 6] = SquareKind.DL;
        Squares[7, 0] = SquareKind.TW;
        Squares[0, 7] = SquareKind.TW;
        Squares[14, 7] = SquareKind.TW;
        Squares[7, 14] = SquareKind.TW;
        Squares[3, 7] = SquareKind.DL;
        Squares[7, 3] = SquareKind.DL;
        Squares[7, 11] = SquareKind.DL;
        Squares[11, 7] = SquareKind.DL;
        Squares[StartPos.row, StartPos.col] = SquareKind.Start;
    }
}

Scrabble.razor

@page "/scrabble"
@Init()

<table class="scrabble-board">
    <tbody>
        @for (int i = 0; i < 15; i++)
        {
        <tr>
            @for (int j = 0; j < 15; j++)
            {
                var (row, col) = (i, j);  // Must store i, j here as row, col for callback with parameter using i and j

                <td class="scrabble-board"
                    style="background-color: @squareColors[row, col]"
                    @onclick="@(() => SquareOnClick(row, col))" />
            }
        </tr>
        }
    </tbody>
</table>

Scrabble.razor.cs

public partial class Scrabble
{
    string[,] squareColors = new string[Board.SIZE, Board.SIZE];
    readonly Dictionary<Board.SquareKind, string> colors = new Dictionary<Board.SquareKind, string>
    {
        [Board.SquareKind.White] = "#DDE0DE",
        [Board.SquareKind.DL] = "#87D7F6",
        [Board.SquareKind.TL] = "#25A9DC",
        [Board.SquareKind.DW] = "#F68787",
        [Board.SquareKind.TW] = "#DB1B1B",
        [Board.SquareKind.Start] = "#25DC88"
    };
    Board board = new Board();

    string Init()  // Method returns a null string to be able to run directly on the Blazor page without compiling error
    {
        for (int i = 0; i < Board.SIZE; i++)
            for (int j = 0; j < Board.SIZE; j++)
            {
                var kind = board.Squares[i, j];
                squareColors[i, j] =colors[kind];
            }
        return null;
    }

    void SquareOnClick(int row, int col)
    {
        Console.Write("(before) {0} ", squareColors[0, 0]);
        squareColors[0, 0] = squareColors[row, col];
        Console.WriteLine("(after) {0}", squareColors[0, 0]);
    }
}

为了更好看,我还使用了以下 CSS(在 wwwroot/index.html 中引用)

.scrabble-board table {
    width: 100%;
    padding-top: 100%
}

.scrabble-board td {
    border: 1px solid black;
    border-radius: 5px;
    width: 50px;
    height: 50px;
    background-size: contain;
}

【问题讨论】:

    标签: c# arrays string blazor


    【解决方案1】:

    删除@Init()并通过覆盖OnInitialized()进行初始化

    using Microsoft.AspNetCore.Components;
    
    public partial class Scrabble : ComponentBase
    {
    
    ...
    
        protected override void OnInitialized()
        {
            for (int i = 0; i < Board.SIZE; i++)
                for (int j = 0; j < Board.SIZE; j++)
                {
                    var kind = board.Squares[i, j];
                    squareColors[i, j] = colors[kind];
                }
        }
    
    ...
    
    

    每次重绘渲染片段时,您都会初始化板。将 0,0 设置为其默认红色。

    【讨论】:

    • 非常感谢!终于让它工作了,我也明白了为什么 List 可以在 UI 上工作,但在幕后并不是我的意图
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多