我正在为学校编写一个简单的井字游戏。作业是用C++进行的,但老师已授予我使用C#和WPF的权限。我已经完成了所有的游戏逻辑,并且表单大部分都已完成,但是我碰到了墙。我目前正在使用Label来指示轮到谁了,我想在玩家做出有效举动时对其进行更改。根据Applications = Code + Markup,我应该能够使用FindName类的Window方法。但是,它一直返回null。这是代码:

public TicTacToeGame()
{
    Title = "TicTacToe";
    SizeToContent = SizeToContent.WidthAndHeight;
    ResizeMode = ResizeMode.NoResize;

    UniformGrid playingField = new UniformGrid();
    playingField.Width = 300;
    playingField.Height = 300;
    playingField.Margin = new Thickness(20);

    Label statusDisplay = new Label();
    statusDisplay.Content = "X goes first";
    statusDisplay.FontSize = 24;
    statusDisplay.Name = "StatusDisplay"; // This is the name of the control
    statusDisplay.HorizontalAlignment = HorizontalAlignment.Center;
    statusDisplay.Margin = new Thickness(20);

    StackPanel layout = new StackPanel();
    layout.Children.Add(playingField);
    layout.Children.Add(statusDisplay);

    Content = layout;

    for (int i = 0; i < 9; i++)
    {
        Button currentButton = new Button();
        currentButton.Name = "Space" + i.ToString();
        currentButton.FontSize = 32;
        currentButton.Click += OnPlayLocationClick;

        playingField.Children.Add(currentButton);
    }

    game = new TicTacToe.GameCore();
}

void OnPlayLocationClick(object sender, RoutedEventArgs args)
{
    Button clickedButton = args.Source as Button;

    int iButtonNumber = Int32.Parse(clickedButton.Name.Substring(5,1));
    int iXPosition = iButtonNumber % 3,
        iYPosition = iButtonNumber / 3;

    if (game.MoveIsValid(iXPosition, iYPosition) &&
        game.Status() == TicTacToe.GameCore.GameStatus.StillGoing)
    {
        clickedButton.Content =
            game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O";
        game.MakeMoveAndChangeTurns(iXPosition, iYPosition);

        // And this is where I'm getting it so I can use it.
        Label statusDisplay = FindName("StatusDisplay") as Label;
        statusDisplay.Content = "It is " +
            (game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O") +
            "'s turn";
    }
}

这里发生了什么?我在两个地方都使用了相同的名称,但是FindName找不到它。我尝试使用Snoop查看层次结构,但是该表单未显示在要选择的应用程序列表中。我在StackOverflow上搜索后发现should be able to use VisualTreeHelper class,但我不知道如何使用它。

有任何想法吗?

最佳答案

FindName在调用控件的XAML名称范围上运行。在您的情况下,由于控件是完全在代码中创建的,因此XAML名称范围为空-这就是FindName失败的原因。参见this page:



解决问题的最简单方法是将对StatusDisplay标签的引用存储为类中的私有(private)成员。或者,如果您想学习如何使用VisualTreeHelper类,则可以使用一个代码片段at the bottom of this page遍历可视树以找到匹配的元素。

(编辑:当然,如果您不想存储对标签的引用,则调用RegisterName的工作要比使用VisualTreeHelper的工作少。)

如果您打算以任何深度使用WPF/Silverlight,建议您完整阅读第一个链接。有用的信息。

关于c# - FindName返回null,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2214737/

10-10 06:14