Как я могу получить положение текстового поля, которое было нажато?
Я пишу в WPF Sudoku Game, и я делаю во время выполнения 81 текстовое поле на canvasе:
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, потому что его make во время выполнения
но если я напишу этот метод:
- Утечка памяти WPF CreateBitmapSourceFromHBitmap ()
- Уведомлять ObservableCollection при изменении позиции
- Правильная проверка с помощью MVVM
- Какие приложения WPF реального мира существуют?
- Как применить правило пользовательской сортировки к WPF DataGrid?
private void canvas1_KeyDown(object sender, KeyEventArgs e) { if (sender.GetType().Name == "TextBox")//the sender is canvas { } }
как я могу получить текстовое поле, в которое пользователь вводит номер? Помощь PLS …
- Различные шаблоны представлений / данных на основе переменной-члена
- Могут ли привязки создавать утечки памяти в WPF?
- DataTrigger, где значение НЕ равно нулю?
- Имя не существует в ошибке пространства имен в XAML
- WPF Databinding: как мне получить доступ к «родительскому» контексту данных?
- Как работает свойство WPF Button.IsCancel?
- Этот тип CollectionView не поддерживает изменения в SourceCollection из streamа, отличного от streamа Dispatcher
- В чем разница между ContentControl и ContentPresenter?
ОК. Удалите весь свой код и начните все заново.
Так вы делаете доску Sudoku в WPF:
XAML:
Код:
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(); 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; } } }
ViewModel:
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)); } }
Как вы можете видеть, Im никоим образом не создает или не манипулирует элементами пользовательского интерфейса в коде. Это просто неправильно в WPF. Вы должны изучить MVVM и понять, что пользовательский интерфейс - это не данные. Данные - это данные. Пользовательский интерфейс - это пользовательский интерфейс
Теперь, когда вам нужно действовать против значения в текстовых блоках, просто действуйте против public int Value
свойства public int Value
в ViewModel. Логика вашего приложения и ваш пользовательский интерфейс должны быть полностью развязаны.
Просто скопируйте и вставьте мой код в File -> New Project -> WPF Application
и посмотрите результаты для себя. Так выглядит на моем компьютере:
Редактировать:
Я изменил образец для вызова метода при изменении значения.
Пожалуйста, поймите, что вы не должны работать с пользовательским интерфейсом в WPF, а не с DATA. Что вам действительно нужно, так это DATA (ViewModel), а не сам пользовательский интерфейс.
using System.Collections.Generic; using System.Windows; using System.ComponentModel; using System; namespace WpfApplication4 { public partial class Window17 : Window { public List Board { get; set; } public Window17() { InitializeComponent(); var random = new Random(); Board = new List (); 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 OnValueChanged { get; set; } } }
Использовать подключенный обработчик событий
AddHandler(TextBox.KeyDownEvent, new RoutedEventHandler(MyFieldClick));
это будет вызвано для каждого текстового поля внутри вызывающего элемента. Поэтому, если вы разместите это в своем окне, каждое текстовое поле KeyDownEvent будет обработано методом обработчика событий MyFieldClick. В этом случае отправителем является текстовое поле, которое первоначально отправило событие.
Но я aggree с HighCore, вы должны использовать WPF больше. В вашем случае я вижу ItemControls и сетку или лучше UniformGridPanel.
Btw TextChanged может быть более подходящим событием для вашего случая.