【问题标题】:How can I get the Position of textbox that has been pressed?如何获取已按下的文本框的位置?
【发布时间】:2013-03-11 16:48:13
【问题描述】:

我正在 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
            {

            }
        }

如何获取用户输入数字的文本框? 请帮助...

【问题讨论】:

  • 这不是在 WPF 中做事的正确方法。不要在程序代码中创建或操作 UI 元素。创建一个合适的 DataTemplate 并使用 ItemsControl。
  • 请看我的回答。
  • 我有这个任务,我不知道wpf...不容易,谢谢大家的帮助!!

标签: c# .net wpf


【解决方案1】:

好的。删除所有代码并重新开始。

这就是你在 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 -&gt; New Project -&gt; 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; }

    }
}

【讨论】:

  • 我怎样才能得到按下的文本框?
  • @LenaTrushevsky 你要那个干什么?
  • @LenaTrushevsky 请告诉我你需要做什么,我可以给你一个方法。您实际上并不需要获得对 UI 的“引用”。
  • 我需要检查按下的文本框的值。我想使用方法 public bool ChkLine(int line, string num) 我需要得到线
  • @LenaTrushevsky 您可以将ItemsControl 更改为ListBox,但我仍然不明白您要执行哪种方法。
【解决方案2】:

使用附加的事件处理程序

AddHandler(TextBox.KeyDownEvent, new RoutedEventHandler(MyFieldClick));

这将被调用元素内的每个文本框调用。因此,如果您将它放在窗口中,每个文本框 KeyDownEvent 都会被修补到 MyFieldClick 事件处理程序方法。在这种情况下,发送者是最初发送事件的文本框。

但我同意 HighCore,你应该更多地使用 WPF。在您的情况下,我看到 ItemControls 和一个 Grid 或更好的是 UniformGridPanel。

顺便说一句,TextChanged 可能更适合您的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    相关资源
    最近更新 更多