将文本框数据传输到我的ViewModel

本文关键字:我的 ViewModel 数据传输 文本 | 更新日期: 2023-09-27 18:02:37

我有两个带有userinput的文本框,我需要将其中的数据传输到我的ViewModel。我试着通过将其绑定到按钮来实现这一点(因为传输应该在单击按钮时发生),但大多数建议使用绑定。然而,要使用绑定,您必须在ViewModel中声明属性(afaik),但由于这些字符串用于创建新对象,因此为它们保留属性几乎是理想的,因为两个文本框将来可能会扩展到10多个。我也试着搞乱CommandParameter,但我似乎只能声明一个。

所以澄清一下:我如何将两个(或更多)文本框的内容传输到相应的ViewModel,以便我可以用它们创建一个新的对象?

编辑:此外,我还希望能够在处理数据的方法成功完成后将Text=字段重置为空。

视图
<TextBox Name="UI1"/>
<TextBox Name="UI2"/>
<Button Source="*ImageSource*" Command="{Binding CallCreateObject}"/>

和ModelView

private void OnCallCreateObject()
{
   Object newObject = new Object(UI1, UI2, false)
}

这是我想要达到的一个一般的例子

将文本框数据传输到我的ViewModel

如果你想在Button Click上从UI插入数据到ViewModel,那么就没有理由使用绑定。绑定主要用于在UI和底层模型之间同步数据。

如果你只需要button_click事件,你可以这样做。

private void button_Click(object sender, RoutedEventArgs e)
    {
        Model model = new Model();
        model.Property1 = textBox1.Text;
        model.Property2 = textBox2.Text;
        textBox1.Text = string.Empty;
        textBox2.Text = string.Empty;
    }

这将解决你的问题。但是当你有一个更好的东西叫做'Binding'

时,不建议使用这种方法

如果你想绑定你的视图与视图模型,那么试试这个:

你的视图模型:

public class Person : INotifyPropertyChanged
  {
      private string name;
      // Declare the event
      public event PropertyChangedEventHandler PropertyChanged;

  public string PersonName
  {
      get { return name; }
      set
      {
          name = value;
          // Call OnPropertyChanged whenever the property is updated
          OnPropertyChanged("PersonName");
      }
  }
  // Create the OnPropertyChanged method to raise the event
  protected void OnPropertyChanged(string name)
  {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
          handler(this, new PropertyChangedEventArgs(name));
      }
  }

}

很好,您已经设置了视图模型。现在视图:

XML PersonView.xml:

<Grid Name="MyContainer">
   <TextBox Text="{Binding PersonName}" />
  <Button Name="SaveInfoButton" OnClick="SaveInfoButton_Click">Save info</Button>
</Grid>

现在我们已经指示了文本框将与哪个属性绑定,让我们向视图指示将用于更新名为PersonName的属性的模型。这个想法是,当您单击按钮时,我们的模型Person的属性PersonName将使用TextBox的值更新。

xml类:

public partial class PersonView : UserControl 
{
  private readonly Person Model;
  public PersonView()  
 {
    //Components initialization, etc. etc...

    this.Model = new Person(); 
    this.DataContext = this.Model;  // Here we are binding the model with our view.
 }
 private void SaveInfoButton_Click(object sender, RoutedEventArgs e)
{
      MessageBox.Show(this.Model.PersonName); // this will print the value of your textbox.
    }
        }

不知道你是否注意到,当用户点击按钮时,我们不需要创建一个新的对象。我们只是使用我们的模型并更新模型属性。如果你在你的视图中添加更多的文本框,你将不得不添加到我们的视图模型以及给出的例子。

这里有一些帖子可以帮助你更多一点(没有足够的时间)

http://blog.scottlogic.com/2012/04/20/everything-you-wanted-to-know-about-databinding-in-wpf-silverlight-and-wp7-part-two.html

http://www.tutorialspoint.com/wpf/wpf_data_binding.htm

你可以这样使用绑定:

<TextBox Name="UI1" Text="{Binding Path=Ut1Value}"/>
<TextBox Name="UI2" Text="{Binding Path=Ut2Value}"/>
<Button Source="*ImageSource*" Command="{Binding CreateTheThingCommand}"/>                

然后在你的视图模型中,你需要有这些属性和命令:

private string _ut1Value;
private string _ut2Value;
public string Ut1Value
{
    get
    {
        return _ut1Value;
    }
    set
    {
        if (_ut1Value!= value)
        {
            _ut1Value= value;
            OnPropertyChanged("Ut1Value");
        }
    }
}
public string Ut2Value
{
    get
    {
        return _ut2Value;
    }
    set
    {
        if (_ut2Value!= value)
        {
            _ut2Value= value;
            OnPropertyChanged("Ut2Value");
        }
    }
}

public ICommand CreateTheThingCommand
{
    get { return new RelayCommand(CreateTheThing); }
}
private void CreateTheThing()
{
    Object newObject = new Object(_ut1Value, _ut2Value, false);
    // Do whatever with your new object
}

听起来好像你至少需要两个ViewModel对象:

  1. 用于显示来自现有对象的数据。这将是,基本上,你已经有了。
  2. 容器视图模型。这封装了IEnumerable对象集合的行为,包括Add新对象所需的功能。

容器ViewModel将具有您正在努力的属性,加上CreateObject命令,以及IEnumerable (ObservableCollection)属性来保存现有的ViewModel对象。

在你的视图中,你将有一个控件来显示现有ViewModel对象中的数据,第二个控件有一个ListView(或类似的)控件来显示现有的视图控件和TextBox控件集,再加上一个按钮来创建一个新对象(并将其添加到列表中)。

这也允许你在容器ViewModel中添加'remove', 'sort'等功能,而不必改变现有的ViewModel

用最少的代码行来完成可伸缩的解决方案的一种方法是创建一个您在视图模型中绑定的项列表。这样你就可以在UI中使用ItemsControl为每个项目显示一个文本框:

public class ViewModel
{
    public List<Item> Items {get;} = new List<Item>
    {
        new Item { Value = "UI1" },
        new Item { Value = "UI2" },
    };
    public class Item
    {
        public string Value {get;set;}
    }
}

视图:

<ItemsControl ItemsSource="{Binding Test}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Value}" Margin="5"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Commit" Margin="5" Click="ButtonBase_OnClick"/>

然后您可以通过单击事件或命令创建对象:

private void OnCallCreateObject()
{
   Object newObject = new Object(Items[0], Items[1], false);
}       

缺点是条目的顺序不明确,因此您需要假设索引顺序是正确的,或者手动排序。