代码之家  ›  专栏  ›  技术社区  ›  Cristián Romo

findname返回空值

  •  5
  • Cristián Romo  · 技术社区  · 15 年前

    我在为学校写一个简单的游戏。作业是用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";
        }
    }
    

    怎么回事?我在两个地方都用同一个名字,但是 发现名 找不到。我试过使用snoop查看层次结构,但是表单没有显示在要选择的应用程序列表中。我在StackOverflow上搜索发现 should be able to use VisualTreeHelper class ,但我不知道怎么用。

    有什么想法吗?

    2 回复  |  直到 13 年前
        1
  •  6
  •   Ben M    15 年前

    FindName 对调用控件的xaml命名空间进行操作。在您的例子中,由于控件完全在代码中创建,因此xaml名称范围是空的——这就是为什么 发现名 失败。见 this page :

    在初始加载和处理之后,对元素树的任何添加都必须为定义xaml名称范围的类调用registername的适当实现。否则,添加的对象不能通过findname等方法被name引用。仅仅设置名称属性(或x:name属性)不会将该名称注册到任何xaml名称作用域中。

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

    (编辑:当然,打电话来的工作量要少一些) RegisterName 如果不想存储对标签的引用,则使用visualtreeheloper。)

    如果您打算在任何深度使用wpf/silverlight,我建议您完整地阅读第一个链接。有用的信息。

        2
  •  2
  •   Chris Barlow Pete Lomax    13 年前

    必须为窗口创建新的名称范围:

    NameScope.SetNameScope(this, new NameScope());
    

    然后在窗口中注册标签的名称:

    RegisterName(statusDisplay.Name, statusDisplay);
    

    所以这似乎就是你要做的 FindName() 工作。