MVVM 创建视图模型



有人可以向我解释如何准确地为 MVVM 模式创建 ViewModel。我试图理解这里的教程:http://msdn.microsoft.com/en-us/magazine/dd419663.aspx,但我无法理解代码中到底发生了什么。

假设我们要创建一个基本应用程序,用于从本地数据库获取人员以及向本地数据库添加人员,并在视图中显示他们。ViewModel 应该是什么样子,以及如何为其创建 RelayCommand。首先,为什么我们要设置变量两次:一次是私下,一次是公开的。

编辑:感谢您到目前为止的帮助。我还有一件事我不知道要做 - 如何将视图绑定到 ViewModel,反之亦然

这是模型:

public class Student : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    private string name;
    private string surname;
    private string age;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }
    public string Surname
    {
        get
        {
            return surname;
        }
        set
        {
            surname = value;
            OnPropertyChanged("Surname");
        }
    }
    public string Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
            OnPropertyChanged("Age");
        }
    }
}

这是视图模型:

public class MainViewModel : ViewModelBase
{
    ObservableCollection<Student> studentList;
    Student selectedPerson;
    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; }
    }
    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();
                    studentList.Add(student);
                }));
        }
    }
}

我已经找到了一种使用Csharp中的视图代码将ViewModel绑定到视图的方法,但是如何将视图绑定到ViewModel的问题仍然存在。更具体地说,如何使用用户在视图中输入的值创建新学生。

下面是视图的 XAML 代码

<Window x:Class="MVVMLight.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" 
    SizeToContent="WidthAndHeight">
<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>

这是视图的Csharp代码

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

我有一些关于视图和视图模型之间的绑定的问题:使用这种类型的绑定的优缺点是什么?如果要使用数据库,最好的绑定方法是什么?

  1. 这就是视图模型和模型应该是什么样子的吗
  2. 如何创建用于将学生添加到可观察集合的中继命令
  3. 为什么我们先私下设定事情,然后再公开[回答]
  4. 如何将视图绑定到视图模型,反之亦然
在你的

属性资源库中,你应该检查新值是否等于旧值,如果是,你应该返回而不是触发 PropertyChanged 事件。

至于你的问题:

  1. 是的,这看起来不错。
  2. 有几种方法可以设置中继命令。 我更喜欢

    private RelayCommand<Student> _addStudentCommand;
    public ICommand AddStudentCommand
    {
        get
        {
            return _addStudentCommand
                ?? (_addStudentCommand = new RelayCommand<Student>((student) =>
                    {
                         studentList.Add(student);
                    }));
        }
    }
    

另一种方式,无需传入学生对象

private RelayCommand _addStudentCommand;
    public ICommand AddStudentCommand
    {
        get
        {
            return _addStudentCommand
                ?? (_addStudentCommand = new RelayCommand(() =>
                    {
                        Student student = new Student(); 
                        studentList.Add(student);
                    }));
        }
    }
  1. 这就是属性在 .net 中的工作方式,您可以使用自动属性,但由于您需要在 setter 中触发更改通知,因此您必须声明属性将对其工作的字段。

另外,由于看起来您正在使用 mvvm light,因此您应该尝试代码片段。 它们使属性非常容易创建。 键入 MVVVMminPC 然后点击两次 Tab。 然后填写突出显示的部分并点击选项卡,直到完成。

您可以通过几种方式将视图绑定到视图模型。我知道这是一个反模式,但你可以使用定位器。基本思想是将视图模型设置为视图数据上下文。

public class Locator
{
   public Viewmodel1 Viewmodel1
    {
       return new Viewmodel1();
    }   
}  

然后,在 app.xaml 中添加此类

<Application.Resources>
   <Locator x:key="VMLocator" />
</Application.Resources>

然后在你看来 xaml

<Page  DataContext="{Binding Source="{StaticResource VMLocator}" Path=ViewModel1}">
</Page>

相关内容

  • 没有找到相关文章

最新更新