簡體   English   中英

FindName返回null

[英]FindName returning null

我正在為學校寫一個簡單的tic tac toe游戲。 作業是用C ++編寫的,但老師允許我使用C#和WPF作為挑戰。 我已經完成了所有游戲邏輯並且表單大部分都已完成,但我遇到了一堵牆。 我目前正在使用一個Label來表明它是誰,我希望在玩家進行有效移動時更改它。 根據Applications = Code + Markup ,我應該能夠使用Window類的FindName方法。 但是,它一直返回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上搜索並發現我應該可以使用VisualTreeHelper類 ,但我不明白如何使用它。

有任何想法嗎?

FindName在調用控件的XAML名稱范圍上運行。 在您的情況下,由於控件完全在代碼中創建,因此XAML名稱范圍為空 - 這就是FindName失敗的原因。 這個頁面

初始加載和處理后對元素樹的任何添加都必須為定義XAML名稱范圍的類調用RegisterName的相應實現。 否則,添加的對象不能通過FindName等方法按名稱引用。 僅設置Name屬性(或x:Name Attribute)不會將該名稱注冊到任何XAML名稱范圍中。

解決問題的最簡單方法是將類中的StatusDisplay標簽的引用存儲為私有成員。 或者,如果您想學習如何使用VisualTreeHelper類,則可以在此頁面底部找到一個代碼片段用於遍歷可視樹以查找匹配元素。

(編輯:當然,如果你不想存儲對標簽的引用,那么調用RegisterName比使用VisualTreeHelper要少。)

如果您計划在任何深度使用WPF / Silverlight,我建議您完整閱讀第一個鏈接。 有用的信息。

您必須為您的窗口創建一個新的NameScope:

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

然后在窗口中注冊標​​簽名稱:

RegisterName(statusDisplay.Name, statusDisplay);

所以這似乎是使FindName()工作所需要做的全部工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM