文本框很多,如何管理? MVVM WPF

A lot of textboxes, how to manage? MVVM WPF

我正在写一些应用程序,输入 64 字节用于通过某种通信标准发送。应用程序必须在每个文本框中有一个字节,所以我需要 64 个文本框。这意味着我必须制作 64 "NotifyPropertyChanged" getter/setter 个函数。或者有什么更好的方法吗?

如果没有更好的方法,如何管理所有这些功能?仅将这 64 个函数粘贴到特殊 class 文件中并连接到我的视图模型?以及如何连接它?例如还是其他?

我总共需要 64 个文本框用于发送,然后还需要 64 个(文本块)用于接收消息。是的,可以在一个文本框中制作所有内容,但我不在这里做决定:)

我还需要限制字符输入到文本框中 - 0-9 和 A-F。

我是 MVVM 和 WPF 的新手,如果这是一个愚蠢的问题,我深表歉意。如有其他问题请追问。

绑定支持数组,因此只需在视图模型中添加一个数组即可:

    public class MyViewModel
    {
        private int[] _Vals = new int[64];
        public int[] Vals { get { return this._Vals; } }
    }

并将每个文本框绑定到 XAML:

中的一个元素
<StackPanel Orientation="Vertical">
    <TextBox Text="{Binding Vals[0], UpdateSourceTrigger=PropertyChanged}" />
    <TextBox Text="{Binding Vals[1], UpdateSourceTrigger=PropertyChanged}" />
    <TextBox Text="{Binding Vals[2], UpdateSourceTrigger=PropertyChanged}" />
    <TextBox Text="{Binding Vals[3], UpdateSourceTrigger=PropertyChanged}" />
    ... etc ...
</StackPanel>

考虑为一个字节创建一个 ViewModel(包含 INotifyPropertyChanged 的​​实现)并将其 64 个实例添加到一个集合中。

然后您可以使用 ItemsControl 来显示文本框并使用集合来获取所有字节。

要限制文本框只允许十六进制值,您可以结合使用 ValueConverter 和处理文本框上的按键。

public partial class MainWindow : Window
{
    private const int numberOfBytes = 64;
    private NumbersViewmodel numbers = new NumbersViewmodel(numberOfBytes);
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = numbers;
    }

}

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

public class NumbersViewmodel : ViewModelBase
{
    private ObservableCollection<NumberViewModel> numbers;

    public ObservableCollection<NumberViewModel> Numbers
    {
        get { return numbers; }
        set
        {
            if (numbers != value)
            {
                numbers = value;
                OnPropertyChanged("Numbers");
            }
        }
    }

    public ICommand SendNumbers
    {
        get;
        private set;
    }

    public NumbersViewmodel(int numberOfNumbers)
    {
        sendNumbers = new SimpleCommand(SendNumbersExecuted);
        this.Numbers = new ObservableCollection<NumberViewModel>();
        for (int i = 0; i < numberOfNumbers; i++)
        {
            this.Numbers.Add(new NumberViewModel());
        }
    }

    private void SendNumbersExecuted()
    {
        ///DoSomethingWith(Numbers);
    }
}

public class NumberViewModel : ViewModelBase
{
    private byte number;

    public byte Number
    {
        get { return number; }
        set
        {
            if (number != value)
            {
                number = value; 
                OnPropertyChanged("Number");
            }
        }
    }
}

public class SimpleCommand : ICommand
{
    private Action execute;
    public SimpleCommand(Action execute)
    {
        this.execute = execute;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        if (execute != null && CanExecute(parameter))
        {
            execute();
        }
    }
}

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <ScrollViewer>
        <ItemsControl ItemsSource="{Binding Numbers}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Number}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
    <Button Grid.Row="1"
            Command="{Binding SendBytes}">Send the bytes</Button>

</Grid>