【问题标题】:Moving behind code to a viewModel class binding将代码移至 viewModel 类绑定
【发布时间】:2016-05-13 19:28:37
【问题描述】:

在了解了ObservableCollectionINotifyPropertyChanged 之后,我正在尝试使用它们将我的代码分成MVVM

但是我在代码隐藏类之外绑定时遇到了一些麻烦。

我的应用程序有三个框,可让您输入一个人的姓名、收入、年龄。然后它将它们显示在 DataGrid 上。

xaml:

<Window x:Class="myApp.MainWindow"
 [...]

  <Grid>
     <DataGrid  x:Name="peopleDisplay">
     </DataGrid>
  </Grid>    

</Window>

在 MainWindow.xaml.cs 中(无结构)

 public partial class MainWindow : Window
 {
    private ObservableCollection<Person> peopleList = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();

        peopleDisplay.ItemsSource = peopleList;

    }

    private void btnAddProduct_Click(object sender, RoutedEventArgs e)
    {

      peopleList.Add(new Person { personName = nameBox.text, income = incomebox.text, age = ageBox.text });

      }

    [...]
   }


class People : INotifyPropertyChanged
 {
    private string personName;

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    public string PersonName {
        get
        {
            return this.personName;
        }
        set
        {
            if( this.personName != value)
            {
                this.PersonName = value;
                this.NotifyPropertyChanged("PersonName");
            }

        }
    }
    public int age { get; set; }
    public double income { get; set; }
}

我的主要问题:

所以现在我尝试做两件事:添加一个新函数来计算每个人的总收入,将上面的 ObservableCollection 移动到 viewModel 类

  1. 现在在新的 viewModel 类中我有ObservableCollection personList(而不是在代码后面),但是把计算方法和属性也放在这里有错吗?如果我将计算属性放在这里,这个 viewModel 将继承 INotifyPropertyChanged,所以当 totalIncome 属性更改时,它会自动更改 UI。但是,将它放在 person 模型中是没有意义的,因为该类代表一个人。

  2. 如何将 viewModel 中的人员列表绑定到 xaml?如果列表在代码隐藏中,我可以做peopleDisplay.ItemsSource = peopleList;,但是这个viewModel 是一个类而不是ObservableCollection 对象,我不能将它设置为dataGrid 的ItemsSource。有没有办法在 viewModel 类中绑定它?我正在学习 mvvm,所以我也可能在这里做错了。请指教

【问题讨论】:

  • 你必须再次分离你的类,比如 ViewModel 和 Model,并且你的 Model 包含像一个人这样的单个实例,然后你的 View Model 将保存人员列表。
  • 是的,代码是在分离之前,我现在试图将它分开,所以我问了两个问题以确保我的方法是正确的,因为我在分离后的绑定部分遇到了一些问题

标签: c# wpf xaml mvvm


【解决方案1】:

您的Model 类是人。如下:

public class People : INotifyPropertyChanged
{
    private string personName;

    public event PropertyChangedEventHandler PropertyChanged;


     protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
       { 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       }

    public string PersonName
    {
        get
        {
            return this.personName;
        }
        set
        {
            if( this.personName != value)
            {
                this.PersonName = value;
                this.NotifyPropertyChanged();
            }
        }
    }

    public int Age { get; set; }
    public double Income { get; set; }
}

您的ViewModel 如下所示:

public class PeopleViewModel 
{
    Public List<People> ListOfPeople { get; set; }
}

ViewModel可以实现INotifyPropertyChanged接口通知视图。

现在您可以将数据上下文设置为PeopleViewModel 并将您的ListOfPeople 绑定到您的DataGrid

为您的View 设置DataContext,您可以从 XAML 或代码后面进行。

在您的View 中为您的DataGrid 设置ItemsSource

XAML:

<Window x:Class="myApp.MainWindow" DataContext="{Binding PeopleViewModel }">
    <Grid>
        <DataGrid  x:Name="peopleDisplay" ItemSource={Binding ListOfPeople}>
            ......
        </DataGrid>
    </Grid> 
</Window>

Reference 1

Reference 2

【讨论】:

  • 好的,所以在你的 XAML 示例中,我会这样做: 然后在使用 PeopleViewModel pVM = new PeopleViewModel() 初始化 peopleViewModel 后的代码隐藏中我会做dataGrid1.ItemSource = pVM?我正在学习绑定,不确定是否要这样绑定。
  • 哦,谢谢,我想我以前不明白 dataContext 到底在做什么。不过还有一个问题。我看到您使用List 而不是 ObservableCollection。这是否意味着我使用 ObservableCollection 的代码是不必要的?
  • 您必须在 ViewModel 中使用 ObservableCollection 才能让 UI 知道您何时将某人添加到列表中
  • @AbinMathew - 如果可以的话,只是为了添加更多您的帖子 - 在调用 NotifyPropertyChanged 时,我更喜欢传入 nameof(TheProperty),而不是在属性字符串中进行硬编码姓名。如果涉及到重构属性名称,并且必须返回所有调用以更新字符串,您可能会遇到一大堆问题。除此之外,很好的答案。
  • @GeoffJames 完全同意您的观点,请检查我的编辑。谢谢
【解决方案2】:

1) 我认为您的方法没有任何问题,但是,如果有一天您想测试计算“TotalIncome”的方法会发生什么?您可以在帮助程序类中分离计算。

2) 首先,您必须使用公共属性在 ViewModel 中公开该集合。话虽如此,您必须在您的 xaml 文件中声明绑定。

<DataGrid  x:Name="peopleDisplay"
           ItemsSource="{Binding MyPropertyOnViewModel}">
</DataGrid>

不要忘记使用视图模型设置窗口的 DataContext。

【讨论】:

    猜你喜欢
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 2017-02-11
    • 2021-06-16
    • 2015-09-09
    • 1970-01-01
    相关资源
    最近更新 更多