Update a binding that does not implement the IObservable collection
As suggested by Thormod, the preferred methods would be changing the collection to ObservableCollection or the INotifyCollectionChanged implementation on the collection will take care of updating the UI.
However, if these options are not available, you can "force" the update using INotifyPropertyChanged on any class that contains the collection. We'll then process the list just like a regular property and use a setter to notify the changes. This requires re-assignment of the reference, so it is recommended to use something like ObservableCollection and also to raise the PropertyChanged event.
Here's a quick example showing how this can only be done with a standard generic list:
public partial class Window1 : Window, INotifyPropertyChanged
{
public Window1()
{
InitializeComponent();
this.Names = new List<string>() { "Mike", "Robert" };
this.DataContext = this;
}
private IList<string> myNames;
public IList<string> Names
{
get
{
return this.myNames;
}
set
{
this.myNames = value;
this.NotifyPropertyChanged("Names");
}
}
private void OnAddName(object sender, RoutedEventArgs e)
{
Names.Add("Kevin");
Names = Names.ToList();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Xaml:
<Window x:Class="Sample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300">
<Grid>
<StackPanel>
<ListBox ItemsSource="{Binding Names}" />
<Button Content="Add Name"
Click="OnAddName" />
</StackPanel>
</Grid>
a source to share
Without further information on how and where this collection is used, here are some pointers that might help you.
- If the collection is not sealed, you can inherit from it.
- If the collection is sealed, you can create an adapter class that contains an instance of your collection and wraps all the appropriate methods.
Either way, your new class can be implemented IObservableCollection
and used for binding.
a source to share
You can set the update binding explicitly and then initiate the update through code, for example by clicking the update button.
As an example.
<StackPanel>
<ListBox
x:Name="lb"
ItemsSource="{Binding SomeList, UpdateSourceTrigger=Explicit}"
/>
<Button Content="Refresh" Click="Refresh_Click" />
</StackPanel>
private void Refresh_Click(object sender, RoutedEventArgs e)
{
BindingExpression be = lb.GetBindingExpression(ListBox.ItemsSourceProperty);
be.UpdateSource();
}
a source to share
You can also force refresh in your ViewModel. This is what I saw Josh Smith in his MVVM demo application:
ICollectionView coll = CollectionViewSource.GetDefaultView(myCollection);
if (coll!=null)
coll.Refresh();
myCollection can be any type of collection bound to a view.
Bea Stollnitz has a little more information on CollectionViewSource: http://www.beacosta.com/blog/?m=200608
a source to share