WPF四子棋开发:如何控制动态创建的TextBox控件
WPF动态生成TextBox无法通过名称控制的解决办法
你遇到的问题核心是:WPF动态创建的控件仅设置Name属性不会自动注册到窗口的NameScope中,所以没法直接通过名称定位这些控件。下面给你三种可行的解决方案:
方法一:手动注册NameScope
在窗口构造函数里先初始化NameScope,再给每个动态生成的TextBox注册名称,之后就能通过FindName方法获取控件:
修改后的构造函数代码:
public MainWindow() { InitializeComponent(); // 初始化窗口的NameScope NameScope.SetNameScope(this, new NameScope()); int x = 100; int y = 190; for (int i = 1; i < 43; i++) { TextBox tbx = new TextBox(); tbx.Name = "Field" + i; // 将TextBox注册到NameScope NameScope.GetNameScope(this).RegisterName(tbx.Name, tbx); tbx.Height = tbx.Width = 50; tbx.HorizontalAlignment = HorizontalAlignment.Left; tbx.VerticalAlignment = VerticalAlignment.Top; tbx.Margin = new Thickness(x, y, 0, 0); myGrid.Children.Add(tbx); x += 55; if (i % 7 == 0) { y += 55; x = 100; } } }
按钮点击事件示例(假设按钮名为btnChangeColor):
private void btnChangeColor_Click(object sender, RoutedEventArgs e) { // 修改Field1的背景色为红色 if (FindName("Field1") is TextBox targetTb) { targetTb.Background = Brushes.Red; } }
方法二:用集合存储所有游戏格子
在窗口类里定义集合保存所有动态生成的TextBox,后续直接通过集合操作,效率更高:
首先在窗口类中声明集合:
private List<TextBox> _gameFields = new List<TextBox>();
修改构造函数,将每个TextBox添加到集合:
public MainWindow() { InitializeComponent(); int x = 100; int y = 190; for (int i = 1; i < 43; i++) { TextBox tbx = new TextBox(); tbx.Name = "Field" + i; // 添加到集合 _gameFields.Add(tbx); tbx.Height = tbx.Width = 50; tbx.HorizontalAlignment = HorizontalAlignment.Left; tbx.VerticalAlignment = VerticalAlignment.Top; tbx.Margin = new Thickness(x, y, 0, 0); myGrid.Children.Add(tbx); x += 55; if (i % 7 == 0) { y += 55; x = 100; } } }
按钮点击事件中操作集合:
private void btnChangeColor_Click(object sender, RoutedEventArgs e) { // 找到Name为Field1的TextBox并修改背景色 var targetTb = _gameFields.FirstOrDefault(tb => tb.Name == "Field1"); if (targetTb != null) { targetTb.Background = Brushes.Blue; } // 也可以直接通过索引操作(比如修改第3个格子) // if (_gameFields.Count > 2) // { // _gameFields[2].Background = Brushes.Green; // } }
方法三:遍历容器的子控件查找
不需要额外注册或存储,直接遍历myGrid的Children集合找到目标TextBox:
按钮点击事件代码:
private void btnChangeColor_Click(object sender, RoutedEventArgs e) { foreach (var child in myGrid.Children) { if (child is TextBox tb && tb.Name == "Field5") { tb.Background = Brushes.Yellow; break; } } }
推荐使用方法二,集合操作效率更高,也更适配后续扩展(比如结合MVVM模式绑定数据)。
内容的提问来源于stack exchange,提问作者Luis_Erschig
相关产品推荐
相关产品推荐

