在MVVM框架内使用按钮动态添加文本框

本文关键字:动态 添加 文本 按钮 MVVM 框架 | 更新日期: 2023-09-27 18:14:45

我一直在爬陡峭的WPF山!我想创建一个允许用户动态添加文本框的UI。要做到这一点,他们需要按一个按钮。

我已经设法使用后面的代码创建了这个,但我想向MVVM结构移动,所以我在视图中没有任何代码。我试过ICommand和ObservableCollection,但我错过了一些东西,我不知道在哪里。下面是一个简单的例子。

XAML:非常基本,只有一个按钮,可以添加一行。

<Window x:Class="WPFpractice072514.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFpractice072514"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="mymy" >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" Grid.Row="0" Name="ButtonUpdateArtist"
                Content="Add TextBox" Click="ButtonAddTexboxBlockExecute" />
    </Grid>
</Window>

c#背后的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPFpractice072514
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region members
        int count = 0;
        #endregion
        public MainWindow()
        {
            InitializeComponent();
        }
        private void ButtonAddTexboxBlockExecute(Object Sender, RoutedEventArgs e)
        {
            TextBox t = new TextBox();
            t.Height = 20;
            t.Width = 20;
            t.Name = "button";
            RowDefinition rowDef1;
            rowDef1 = new RowDefinition();
            mymy.RowDefinitions.Add(rowDef1);
            ColumnDefinition colDef1;
            colDef1 = new ColumnDefinition();
            mymy.ColumnDefinitions.Add(colDef1);
            ++count;
            mymy.Children.Add(t);
            Grid.SetColumn(t, 1);
            Grid.SetRow(t, count);
        }
    }
}

问题:我需要什么代码(XAML和c#)才能将方法从后面的代码移到视图模型中?

可以使用命令动态添加文本框吗?

我假设文本框必须保持在一个容器,在这种情况下是什么网格是为。但是,如果我使用一个MVVM,我需要包含在一个列表视图或其他容器使用ItemsSource文本框吗?

在MVVM框架内使用按钮动态添加文本框

遵循以下步骤,您就完成了:

  1. 使用ItemsControl并将其ItemsSource绑定到ViewModel中的一些集合(最好是ObservableCollection)。
  2. 定义ItemTemplate的ItemsControl与TextBox在它。
  3. 在ViewModel中创建一个ICommand,并将其绑定到按钮上。
  4. 在命令行上执行添加集合项,你会看到文本框被自动添加。

XAML :

<StackPanel>
    <Button Content="Add TextBox" Command="{Binding TestCommand}"/>
    <ItemsControl ItemsSource="{Binding SomeCollection}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Path=.}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

ViewModel :

public class MainWindowViewModel : INotifyPropertyChanged
{
    public ObservableCollection<string> SomeCollection { get; set; }
    public ICommand TestCommand { get; private set; }
    public MainWindowViewModel()
    {
        SomeCollection = new ObservableCollection<string>();
        TestCommand = new RelayCommand<object>(CommandMethod);
    }
    private void CommandMethod(object parameter)
    {
        SomeCollection.Add("Some dummy string");
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

RelayCommand :

public class RelayCommand<T> : ICommand
{    
    readonly Action<T> _execute = null;
    readonly Predicate<T> _canExecute = null;
    public RelayCommand(Action<T> execute)
        : this(execute, null)
    {
    }    
    public RelayCommand(Action<T> execute, Predicate<T> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute((T)parameter);
    }    
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }
}

注意 -我假设你知道如何通过设置DataContext使绑定魔法工作来插入View与ViewModel。

[link][1]
 class TestViewModel : BindableBase  
    {  
        private TestModel testModel;  
        public ICommand AddCommand { get; private set; }  
        public TestViewModel(StackPanel stkpnlDynamicControls)  
        {  
            testModel = new TestModel();  
            TestModel.stkPanel = stkpnlDynamicControls;  
            AddCommand = new DelegateCommand(AddMethod);  
        }  
        public TestModel TestModel  
        {  
            get { return testModel; }  
            set { SetProperty(ref testModel, value); }  
        }  
        private void AddMethod()  
        {  
            Label lblDynamic = new Label()  
            {  
                Content = "This is Dynamic Label"  
            };  
            TestModel.stkPanel.Children.Add(lblDynamic);  
        }  
    }