如何在视图(View)和视图模型(ViewModel)之间传递数据

3
我是一个MVVM设计模式的新手,我正在尝试创建一个简单的应用程序,在主窗口中显示学生列表,并希望用户能够将新学生添加到列表中。我已经完成了可观察集合的绑定,其中包含了学生的数据,但是如何通过从文本框中获取数据并将它们用作命令参数来创建新用户呢?
以下是我的视图:
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="2*"/>
        <RowDefinition Height="2*"/>
        <RowDefinition Height="2*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <TextBlock x:Name="NameTextBlock"
               Text="Name"
               Style="{StaticResource TextBlockTextStyle}"/>
    <TextBlock x:Name="SurnameTextBlock"
               Grid.Row="1"
               Text="Surname"
               Style="{StaticResource TextBlockTextStyle}"/>
    <TextBlock x:Name="AgeTextBlock"
               Grid.Row="2"
               Text="Age"
               Style="{StaticResource TextBlockTextStyle}"/>
    <TextBox x:Name="NameTextBox"
             Grid.Column="1"
             Style="{StaticResource TextBoxTextStyle}"/>
    <TextBox x:Name="SurnameTextBox"
             Grid.Row="1"
             Grid.Column="1"
             Style="{StaticResource TextBoxTextStyle}"/>
    <TextBox x:Name="AgeTextBox"
             Grid.Row="2"
             Grid.Column="1"
             Style="{StaticResource TextBoxTextStyle}"/>
    <ListBox x:Name="StudentListBox"
             Grid.ColumnSpan="2"
             Grid.Row="4"
             Style="{StaticResource ListBoxStyle}"
             ItemsSource="{Binding StudentList}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Name}"
                               Style="{StaticResource TextBlockTextStyle}"/>
                    <TextBlock Text="{Binding Surname}"
                               Grid.Column="1"
                               Style="{StaticResource TextBlockTextStyle}"/>
                    <TextBlock Text="{Binding Age}"
                               Grid.Column="2"
                               Style="{StaticResource TextBlockTextStyle}"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Button x:Name="AddButton"
            Grid.Row="7"
            Grid.ColumnSpan="2"
            HorizontalAlignment="Center"
            Content="Add"
            Margin="7,7,7,7"
            Command="{Binding AddStudentCommand}"/>        
</Grid>

这是我的ViewModel

public class MainViewModel : ViewModelBase
{
    ObservableCollection<Student> studentList;
    public MainViewModel()
    {
        //populate some sample data
        studentList = new ObservableCollection<Student>()
        {
            new Student(){Name="John", Surname="Smith", Age="28"},
            new Student(){Name="Barbara", Surname="Anderson", Age="23"}
        };
    }

    public ObservableCollection<Student> StudentList
    {
        get { return studentList; }
        set { RaisePropertyChanged("studentList"); }
    }

    Student selectedPerson;
    public Student SelectedPerson
    {
        get { return selectedPerson; }
        set
        {
            selectedPerson = value;
            RaisePropertyChanged("SelectedPerson");
        }
    }

    private RelayCommand _addStudentCommand;
    public ICommand AddStudentCommand
    {
        get
        {
            return _addStudentCommand
                ?? (_addStudentCommand = new RelayCommand(() =>
                {
                    Student student = new Student();
                    // here should be the logic of defining the name, surname, 
                    // age and id of the newly created student
                    studentList.Add(student);
                }));
        }
    }

}

我在当前项目中使用MVVMLight,但有许多事情我不理解,请解释一下我应该如何传递文本框中的数据以及在使用命令时应该发生什么。

如果需要,请告诉我添加更多代码。


嗨 :) 正如你所说,你没有太多经验,也不太了解MVVM,所以虽然我可以回答这个问题,但我认为最好的做法是提供一些链接给你观看:http://www.youtube.com/watch?v=BClf7GZR0DQ 和 http://channel9.msdn.com/blogs/kreekman/techdays-2010-understanding-the-model-view-viewmodel-pattern。第二个视频是MVVM-light的作者。它们基本上涵盖了相同的材料,但都带有稍微不同的视角! - Immortal Blue
@ImmortalBlue,感谢你的视频,对我帮助很大。 - EnvelopedDevil
2个回答

5

我会在ViewModel中创建一些属性,将文本框绑定到这些属性上。 对于所有三个文本框,可以像这样(在你的ViewModel中):

private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
            RaisePropertyChanged("Name");
        }
    }

接着,在XAML中将文本框的文本绑定到这个属性:

<TextBox x:Name="NameTextBox"
             Text="{Binding Name}"
         Grid.Column="1"
         />

最后,在AddStudent命令中,您引用了绑定到文本框的视图模型中的属性。

private RelayCommand _addStudentCommand;
    public ICommand AddStudentCommand
    {
        get
        {
            return _addStudentCommand
                ?? (_addStudentCommand = new RelayCommand(() =>
                {
                    Student student = new Student();
                    student.Name = this.Name;
                    student.Surname = this.Surname;
                    student.Age = this.Age;
                    // here should be the logic of defining the name, surname, 
                    // age and id of the newly created student
                    _StudentList.Add(student);
                }));
        }
    }

只是出于习惯。通常,如果要将更改传播回业务对象,则需要双向绑定。我编辑了我的帖子并省略了双向绑定。 - Mike Schwartz
这个回答解决了您的问题吗? - Mike Schwartz
是的,谢谢你提供代码,但我这里有一个问题 - 如果我想创建一个不同的类来保存我的数据,我应该如何在任何ViewModel和命令中使用它。 - EnvelopedDevil
我只是给你一个基本的例子,告诉你什么可以工作。你需要给出一个更具体的例子,说明你想要实现什么。WPF非常灵活,你有很多选择。 - Mike Schwartz
当然可以!如果我回答了你的问题,请确保将其标记为已回答 :) - Mike Schwartz
我电脑出了一些技术问题,所以我会暂时离开开发环境。感谢您的帮助,但很抱歉我没有足够的声望来投票支持答案。 - EnvelopedDevil

-1
(从我的评论中调皮地发布)
正如你所说,你没有太多经验,也不太了解MVVM,所以虽然我可以回答这个问题,但我认为最好的做法是提供一些链接给你观看:

youtube.com/watch?v=BClf7GZR0DQ

channel9.msdn.com/blogs/kreekman/

第二个视频是由写MVVM-light的那个人制作的。 它们基本上涵盖了相同的内容,但两者都带来了稍微不同的观点!

1
SO是一个寻求他人帮助和分享知识的地方。"所以,尽管我可以回答这个问题......"如果我们都采取这种态度,那么我们所有人都应该只从教科书中学习。 - TheAppMentor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接