我在WPF中写了数独游戏,我在画布上运行了81个文本框:
public partial class Test : Window
{
private TextBox[,] texts = new TextBox[9, 9];
GameBoard board = new GameBoard();
public Test(string path)
{
InitializeComponent();
Initialization_text();
}
void Initialization_text()
{
for (int i = 0; i < texts.GetLength(0); i++)
{
for (int j = 0; j < texts.GetLength(1); j++)
{
texts[i, j] = new TextBox();
texts[i, j].Name = "txt" + i + j;
texts[i, j].Width = 40;
texts[i, j].Height = 40;
texts[i, j].MaxLength = 1;
texts[i, j].FontSize = 22;
texts[i, j].FontWeight = FontWeights.Bold;
texts[i, j].Foreground = new SolidColorBrush(Colors.DimGray);
texts[i,j].TextAlignment = TextAlignment.Center;
Canvas.SetLeft(texts[i, j], (i+1)*40);
Canvas.SetTop(texts[i, j], (j+1)*40);
canvas1.Children.Add(texts[i, j]);
}
}
}
我需要获取文本框的位置,用户输入的数字用于检查值,但是我无法编写调用TextBoxKeyDown的方法,因为它在运行时生成
但如果我写这个方法:
private void canvas1_KeyDown(object sender, KeyEventArgs e)
{
if (sender.GetType().Name == "TextBox")//the sender is canvas
{
}
}
如何获取用户输入数字的文本框? 请帮忙......
答案 0 :(得分:2)
确定。删除所有代码并从头开始。
这是你在WPF中使用数独游戏板的方法:
XAML:
<Window x:Class="WpfApplication4.Window17"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window17" Height="300" Width="300">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="9" Columns="9"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Column}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Value}" VerticalAlignment="Stretch" FontSize="20" TextAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
代码背后:
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication4
{
public partial class Window17 : Window
{
public Window17()
{
InitializeComponent();
var random = new Random();
var board = new List<SudokuViewModel>();
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
board.Add(new SudokuViewModel() {Row = i, Column = j,Value = random.Next(1,20)});
}
}
DataContext = board;
}
}
}
视图模型:
public class SudokuViewModel:INotifyPropertyChanged
{
public int Row { get; set; }
public int Column { get; set; }
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
NotifyPropertyChange("Value");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChange(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
正如您所看到的,我无法在代码中创建或操作UI元素。这在WPF中是完全错误的。您必须学习MVVM,并了解UI is Not Data. Data is Data. UI is UI
现在,只要您需要对TextBoxes中的Value进行操作,只需对ViewModel中的public int Value
属性进行操作即可。您的应用程序逻辑和UI必须完全分离。
只需将我的代码复制并粘贴到File -> New Project -> WPF Application
中,然后自行查看结果。这是它在我的电脑中的样子:
修改强>
我修改了样本,以便在更改值时调用方法。
请理解,您不应该在WPF中针对UI进行操作,而是针对DATA。 你真正关心的是DATA(ViewModel),而不是UI本身。
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;
using System;
namespace WpfApplication4
{
public partial class Window17 : Window
{
public List<SudokuViewModel> Board { get; set; }
public Window17()
{
InitializeComponent();
var random = new Random();
Board = new List<SudokuViewModel>();
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
Board.Add(new SudokuViewModel()
{
Row = i, Column = j,
Value = random.Next(1,20),
OnValueChanged = OnItemValueChanged
});
}
}
DataContext = Board;
}
private void OnItemValueChanged(SudokuViewModel vm)
{
MessageBox.Show("Value Changed!\n" + "Row: " + vm.Row + "\nColumn: " + vm.Column + "\nValue: " + vm.Value);
}
}
public class SudokuViewModel:INotifyPropertyChanged
{
public int Row { get; set; }
public int Column { get; set; }
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
NotifyPropertyChange("Value");
if (OnValueChanged != null)
OnValueChanged(this);
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChange(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public Action<SudokuViewModel> OnValueChanged { get; set; }
}
}
答案 1 :(得分:0)
使用附加的事件处理程序
AddHandler(TextBox.KeyDownEvent, new RoutedEventHandler(MyFieldClick));
将调用call元素中的每个文本框。因此,如果将其放在窗口中,则每个文本框KeyDownEvent都会修补到MyFieldClick事件处理程序方法。在这种情况下,发件人是最初发送事件的文本框。
但我与HighCore合作,你应该更多地利用WPF。在你的情况下,我看到ItemControls和一个网格或更好的UniformGridPanel。
顺便说一句TextChanged可能是适合您案件的事件。