Reputation: 1934
I am new to WPF and saw few good videos about MVVM and WPF, however I get confused when I try to show a list of data. For some reason I get no data, in my listview. Here is my class
Model/Person.cs
class Person : INotifyPropertyChanged
{
// 1. Fields, Constants
private int ID;
private string FirstName;
private string MiddleName;
private string LastName;
private DateTime Birthday;
private string Prefix;
private string Email;
public Person(int ID, string FirstName, string MiddleName, string LastName)
{
this.ID= ID;
this.FirstName = FirstName;
this.MiddleName = MiddleName;
this.LastName = LastName;
}
/// <summary>
/// Get or Sets the person first name
/// </summary>
public string firstName
{
get { return FirstName; }
set {
FirstName = value;
OnPropertyChanged("FirstName");
}
}
/// <summary>
/// Get or Sets the person middle name
/// </summary>
public string middleName
{
get { return MiddleName; }
set {
MiddleName = value;
OnPropertyChanged("MiddleName");
}
}
/// <summary>
/// Get or Sets the person last name
/// </summary>
public string lastName
{
get { return LastName; }
set {
LastName = value;
OnPropertyChanged("LastName");
}
}
/// <summary>
/// Get or Sets the person birthday
/// </summary>
public DateTime birthday
{
get { return Birthday; }
set {
Birthday = value;
OnPropertyChanged("Birthday");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
Then I have my View/Person.xaml.cs
public partial class Person : Window
{
public Person()
{
InitializeComponent();
lvDataBinding.DataContext = new PersonViewModel();
}
}
The xaml is as follow:
<ListView Margin="10" Name="lvDataBinding" ItemsSource="{Binding Person}" Grid.Column="1" Width="auto" Grid.ColumnSpan="8" Grid.Row="1">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding firstName}" Header="First Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding lastName}" Header="Last Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding middleName}" Header="Middle Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Birthday}" Header="Birthday" Width="100"/>
</GridView>
</ListView.View>
</ListView>
Last pieces but important here is my ViewModel/PersonViewModel.cs
internal class PersonViewModel
{
public ObservableCollection<Person> myData { get; set; }
public PersonViewModel()
{
List<Person> myData = new List<Person>();
}
public ObservableCollection<Person> getData()
{
myData.Add(new Person(12456, "John", "Francis", "Dufour"));
myData.Add(new Person(12456, "Heather", "Meagan", "Cornthwaite"));
if (myData.Count > 0)
{
return myData;
}
else
{
return null;
}
}
}
I am totally of the chart or is something very small that needs to be fix? Also does it actually follow the MVVM pattern, and in the future I plan to have access to a database, does this pattern work well for me in the future for this.
Upvotes: 1
Views: 218
Reputation: 81313
First of all collection name is myData
and not Person
. So, change ItemsSource to bind to myData property:
<ListView ItemsSource="{Binding myData}">
Also, I would suggest to use ObservableCollection<T>
instead of List<T>
in case you want your UI to update on add/remove of item in collection because ObservableCollection implement INotifyCollectionChanged
which is responsible for notifying UI on any change in collection.
Replace
public List<Person> myData {get; set;}
with
public ObservableCollection<Person> myData {get; set;}
Second, you can only bind with properties and not fields. So change all fields in Person class to properties and make them public.
public int ID {get; set;} // Same for other properties.
Since you are implementing INotifyPropertyChanged, make sure you raise the event properly from all property setters. So, ideal property should look like:
private int id;
public int ID
{
get
{
return id;
}
set
{
if(id != value)
{
id = value;
OnPropertyChanged("ID");
}
}
}
Third, binding path property is case sensitive. Make sure you spell the binding correctly:
It should be FirstName instead of firstName.
<GridViewColumn DisplayMemberBinding="{Binding FirstName}"
Header="First Name" Width="100"/> // Same for other columns.
Fourth, you never filled the objects in the collection. Method getData()
is never called. Fill the collection in constructor itself.
public ObservableCollection<Person> myData {get; set;}
public PersonViewModel()
{
myData = new ObservableCollection<Person>();
myData.Add(new Person(12456, "John", "Francis", "Dufour"));
myData.Add(new Person(12456, "Heather", "Meagan", "Cornthwaite"));
}
Upvotes: 3