[英]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.