Reputation: 136
I've got an ObservableCollection
of model objects that I'm attempting to display in the DataGridCells
of a GridView
in a ListView
. For this simplified example, let's say that my model objects all have "MyString," and that I'm attempting to show "MyString" in a TextBlock
inside of each row's DataGridCell
.
As the ObservableCollection
adds or removes these model objects, the ListView
shows the correct number of rows, however the individual cells are empty. How do I properly bind them? Should I be using DataContext
or ItemSource
, and if so, where? Here's a single-column example of one such binding attempt.
<ListView ItemsSource="{Binding MyObservableCollection}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumnHeader Content="My String Data" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataGridCell>
<TextBlock Text="{Binding Path=MyString}">
</TextBlock>
</DataGridCell>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
EDIT: Per Michal Ciechan, I've implemented INotifyPropertyChanged
on my model class, but it didn't seem to change anything. I won't actually be changing the fields on these objects once they're in the collection, however, so this may not be the right approach. Here's some more example code.
The Model:
public class MyModel : INotifyPropertyChanged
{
public string MyString;
public event PropertyChangedEventHandler PropertyChanged;
}
The ViewModel:
ObservableCollection<MyModel> MyObservableCollection = new ObservableCollection<MyModel>();
public void AddModelToCollection()
{
MyModel mm = new MyModel();
mm.MyString = "HELLO WORLD";
MyObservableCollection.Add(mm);
}
Upvotes: 0
Views: 121
Reputation:
public string MyString;
is a field, not a property. You can't bind to fields. You can only bind to properties.
private string _myString;
public string MyString
{
get
{
return _myString;
}
set
{
_myString = value;
OnPropertyChanged("MyString");
}
}
I'll leave the implementation of OnPropertyChanged
to you.
To clarify
This is a PROPERTY:
public string DERP { get; set; }
Notice it has a getter and a setter. The compiler turns this into two methods, one for getting the value and one for setting it.
This is a FIELD:
public string HERP;
Notice, it doesn't have a getter or a setter. It is just a pointer to a value on the stack.
Here comes the important bit:
So setting the value of a field prior to attempting to bind against it matters not. The Binding won't be looking for fields, and therefore won't see it.
Upvotes: 2
Reputation: 13898
Will is right, your Model class needs to have MyString
as a Property rather than field.
What is the difference between a Field and a Property in C#?
WPF - Binding - Binding Source
You can bind to public properties, sub-properties, as well as indexers, of any common language runtime (CLR) object. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine. For more information about how to implement a class that can serve as a binding source, see Implementing a Class for the Binding Source later in this topic.
public class MyModel : INotifyPropertyChanged
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
set
{
_myString = value;
OnPropertyChanged("MyString");
}
}
}
Upvotes: 1