Propagate changes in model to view in Silverlight - silverlight

in my Silverlight 4 Application I have an ObservableCollection that I data bind to two different listboxes. The listboxitems showing the content of the MyClass-Object. When I add an item to the ObservableCollection, the new item is displayed in both listboxes properly.
I have set the Binding Mode to two way, so that editing the listboxitems will update the model automatically. This works so far. My problem is, that the content of the other listbox doesn't update with the updated model. Adding a new item will properly show up on the other listbox, but the updates of the content (which I checked happens) won't.
Any ideas how to achieve: The content of the other listbox should update automatically, when the I update the content in one listbox.
Thanks in advance,
Frank

To expand on what luke said your class needs to implement INotifyPropertyChanged and your properties need to throw the PropertyChanged event in their setters.
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; // This may be named wrong
private string _myString = null;
public string MyString
{
get { return _myString; }
set
{
if(value == _myString)
return;
_myString = value;
var eh = PropertyChanged;
if(eh != null)
eh(this, new PropertyChangedEventArgs("MyString"));
}
}
}
The MyString property will notify the UI that it has changed which will trigger the binding to update.

you need to make sure that your objects in the observable collection implement INotifyPropertyChanged and they should post change events when your content properties change.

Related

How to replace griddata content when another control's (e.g. combobox) selection is changed?

This is probably not that difficult but as a wpf/mvvm beginner I'm still struggling with some basics.
I have a combobox (acts like a filter) and a griddata in a view. I use MMVM and databinding. On startup griddata is populated and the combobox's selection is set - that works fine. I'd like to replace the content of the griddata when the selection in the combobox changes. The combobox selected value is bound to a property in my viewmodel so I know when it changes and I can easily replace the content of the collection (which is IList) bound to the griddata. However I do not know how to force the griddata to 'refresh' itself in the view using mvvm bindings.
I was considering using ObservableCollection<> but from what I've read it looks like replacing the content is not that simple either. I do not really need the view to know when a single item in the collection changes - I will always replace the whole content of the list.
I'd appreciate any suggestions.
You can implement INotifyPropertyChanged in you ViewModel and call it when the List changes.
Example:
public class ViewModel : INotifyPropertyChanged
{
private List<MyObject> _myList;
public List<MyObject> MyList
{
get { return _myList; }
set { _myList = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Now when you replace MyList e.g. MyList = newlist it will tell the UI to update whatever is bound to MyList

WPF ObservableCollection and Listbox.itemsource exception

Editing this entire post to clarify... I cannot seem to nail this:
BackgroundWorker receives data from a WCF service that is a list of objects. The service reference is configured to be ObservableCollection.
I pass the ObservableCollection via a delegate into my main UI thread and set it equal to the UI threads Local Collection.
A listbox is bound to this local collection and does not update. I've added the following to my collection:
public ObservableCollection<EmployeeData> _empData { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<EmployeeData> EmpData
{
get { return _empData ; }
set
{
_empData = value;
OnPropertyChanged("EmpData");
}
}
private void OnPropertyChanged(string p)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(p));
}
This even fires but the PropertyChanged is always null. My XAML listbox has a binding declared as:
ItemsSource="{Binding Path=EmpData}"
No matter what I do EmpData updates but the ListBox does not, I've tried several other methods but nothing ever changes in the listbox, its always just null.
I've been working on this for over a day now, I cannot seem to get this whole automatic updating thing to 'click'.
I'm not sure that I understand exactly what you are doing, but here are a couple of suggestions.
Have a single ObservableCollection
Bind your itemcollection (or listbox, or whatever) to this
Depending on the user, clear and fill that observablecollection with list data
Have the background worker update the list and refresh the observable collection if anything has changed.
Ideally your EmployeeData class will implement the INotifyPropertyChanged interface, so that property changes will get automatically updated in your view.

WPF datagrid binding complex type property back

I have a simple Datagrid binded to an ObservableCollection from the ViewModel. This ObservableCollection is composed by a Custom Type, say ObservableCollection.
The ComplexType only have 2 properties, and only one is editable on the screen. The other one is a bool type that depends on the first.
When I edit the first property, it gets reflected to the ComplexType and it also change the second property. But the second property is not changed on the screen.
How can I update the second property on the screen?
Try this:
public class ComplexType:INotifyPropertyChanged
{
private object someProperty1;
public object SomeProperty1
{
get{return someProperty1;}
set
{
someProperty1=value;
SomeProperty2=somefunc(someProperty1);
If(PropertyChanged!=null){PropertyChanged(this, new PropertyChangedEventArgs(SomeProperty1));}
}
}
private object someProperty2;
public object SomeProperty2
{
get{return someProperty2;}
set
{
someProperty2=value;
If(PropertyChanged!=null){PropertyChanged(this, new PropertyChangedEventArgs(SomeProperty2));}
}
public event PropertyChangedEventHandler PropertyChanged;
}
An observable collection provides notification only when items are added, removed, or the whole collection is refreshed. You need to make sure that each property either raises the PropertyChanged event or is a dependency property if you want your UI to refresh when it changes.

Can't get a DataGrid to update

I have a WPF Toolkit DataGrid bound to an ObservableCollection of Car in my view model. Car has a PropertyChanged event and the setters of each of its two string properties fire the event. I also have the grid's SelectedItem property bound to a property in the view model of type Car, also called SelectedItem.
On the same window as the grid, I have buttons for add, modify and delete. Add and modify open a dialog window with two textboxes, one for each Car property. Delete just shows a confirm dialog then does the delete.
For add and delete, I add or delete an item from the ObservableCollection and the grid updates itself as expected. However, for modify it does not. At first, my Car did not use PropertyChanged and after some searching I found that it needed to for the grid to update when an individual item's properties changed. But now that I am using PropertyChanged, the grid still doesn't update.
I've tried changing the values of the SelectedItem in my view model as well as directly changing the item on the collection.
What am I doing wrong?
Make sure you're implementing INotifyPropertyChanged and not just raising a PropertyChanged event. Also, when raising PropertyChanged, you must pass "this" as the sender, otherwise WPF will ignore the event.
Below is a simple base class that implements INotifyPropertyChanged.
public class Person : INotifyPropertyChanged {
private string name;
public string Name {
get { return name; }
set {
if (name != value) {
name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Sounds like the classic problem with ObservableCollection. ObservableCollection only notifies of additions, deletions, etc. on it's self. It will NOT notify of changes to properties of whatever you have stored in it. This is why your add/delete operations work as expected.
What you should do is use a CollectionView and bind to that:
ObservableCollection<MyObject> myCollection = new ObservableCollection<MyObject>();
ICollectionView view = CollectionViewSource.GetDefaultView(myCollection);
using this method also has the benifit that grouping and sorting are built into the view.

WPF datagrid multiple windows question

I have a scenario where i load an ICollectionView in a datagrid.
In some cases I modify the data where the collectionview gets it's data from. If I then reload the grid with configGrid.ItemsSource = configData; for example, the data gets updated.
Now the thing is, I sometimes open a new window using:
var newWindow = new Edit(movie);
newWindow.Show();
The thing is, I also edit the data using this new window. Now I want the datagrid in the first window to be refreshed after I close this second window (actually, it doesn't matter when it gets refreshed, as long as it does).
How do I do this?
I might be missing something here (I have a crippling hangover unfortunately) but can't you handle the window closed event of newWindow and refresh confiGrids itemsource there?
Window newWindow = new Window();
newWindow.Closed += new EventHandler(newWindow_Closed);
newWindow.Show();
void newWindow_Closed(object sender, EventArgs e)
{
configGrid.ItemsSource = configData;
}
If the collection behind the ICollectionView supports INotifyCollectionChanged (like ObservableCollection) and the object itself supports INotifyPropertyChanged then the grid is supposed to update automatically
Otherwise you are on your own and the editing window should raise some sort of notification (maybe an event) that you should receive and update the list.
Ok, here's the long version:
WPF data-binding can update the UI automatically - but it needs to know that something changed in order to trigger the update, the easiest way to do this is to support INotifyPropertyChanged, let's create simple class:
public class Movie
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
Now, let's add INotifyPropertyChanged support:
public class Movie : INotifyPropertyChanged
{
public event PropertyChanged;
protected virtual OnPropertyChanged(string property)
{
var ev = PropertyChanged;
if(ev!=null)
{
ev(this, new PropertyChangedEventArgs(property));
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
}
Now when you bind to the movie class and change the Name property the UI will be updated automatically.
The next step is to handle a list of Movie objects, we do that by using a collection class the implements INotifyCollectionChanged, luckily for us there's one already written in the framework called ObservableCollection, you user ObservableCollection<T> the same way you would use a List<T>.
So, just bind to ObservableCollection and WPF will automatically detect when objects change or when they are added or removed.
ICollectionView is very useful, it adds support for current item, sorting, filtering and grouping on top of the real collection, if that collection is an ObservableCollection everything will just work, so the code:
ObservableCollection<Movie> movies = new ObservableCollection<Movie>();
ICollectionView view = CollectionViewSource.GetDefaultView(movies);
will give you a collection view that supports automatic change notifications.

Resources