I’m new to WPF and data binding. After wandering around the web for a good practical solution, all I could find were (in my opinion) overly complicated solutions to a problem that will most probably be fixed in the future.

Problem

It seems that when adding or removing elements from an observable collection, data binding works. However, when an element within the collection changes value, the GUI element is not updated.

Solution

For this, I made a new collection class that would implement the ObservableCollection with a Refresh() method which would just raise the collection change event.

Aim - Simplify the process of updating the GUI

My XAML Code

  1. <Button Content="Add" HorizontalAlignment="Left" Margin="366,69,0,0" VerticalAlignment="Top" Width="75" Click="AddDate" />
  2. <ListBox Name="MyListBox" HorizontalAlignment="Left" Height="95" Margin="131,84,0,0" VerticalAlignment="Top" Width="197">
  3. <ListBox.ItemTemplate>
  4. <DataTemplate>
  5. <StackPanel Orientation="Horizontal">
  6. <TextBlock Text="{Binding Now}"></TextBlock>
  7. <CheckBox IsChecked="{Binding IsChecked}"></CheckBox>
  8. </StackPanel>
  9. </DataTemplate>
  10. </ListBox.ItemTemplate>
  11. </ListBox>
  12. <Button Content="Mark All" HorizontalAlignment="Left" Margin="366,94,0,0" VerticalAlignment="Top" Width="75" Click="MarkAll" />
  13. <Button Content="Unmark All" HorizontalAlignment="Left" Margin="366,119,0,0" VerticalAlignment="Top" Width="75" Click="UnMarkAll" />

Class file

  1. namespace WpfApp1 {
  2. //create our test class
  3. public class NowDate {
  4. public string Now {
  5. get;
  6. set;
  7. }
  8. public bool IsChecked {
  9. get;
  10. set;
  11. }
  12. }
  13. //create a new collection class with a refresh method
  14. public class ObservableCollectionPropertyNotify < T > : ObservableCollection < T > {
  15. //OnCollectionChange method is protected, accesible only within a child class in this case. This is why
  16. //I made a new Collection class with a public method Refresh.
  17. public void Refresh() {
  18. for (var i = 0; i < this.Count(); i++) {
  19. this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  20. }
  21. }
  22. }
  23. public partial class MainWindow: Window {
  24. public ObservableCollectionPropertyNotify < NowDate > Dates {
  25. get;
  26. set;
  27. }
  28. public MainWindow() {
  29. InitializeComponent();
  30. //Set up a simple collection with some items.
  31. Dates = new ObservableCollectionPropertyNotify < NowDate > {
  32. new NowDate {
  33. Now = "1", IsChecked = false
  34. },
  35. new NowDate {
  36. Now = DateTime.Now.ToString(), IsChecked = false
  37. }
  38. };
  39. MyListBox.DataContext = this;
  40. MyListBox.ItemsSource = Dates;
  41. }
  42. private void AddDate(object sender, RoutedEventArgs e) {
  43. //in this case GUI updates implicitly. No need to call Refres()
  44. Dates.Add(new NowDate {
  45. Now = DateTime.Now.ToString(), IsChecked = true
  46. });
  47. }
  48. private void MarkAll(object sender, RoutedEventArgs e) {
  49. foreach(var item in Dates)
  50. item.IsChecked = true;
  51. //calling refresh after item has changed
  52. Dates.Refresh();
  53. }
  54. private void UnMarkAll(object sender, RoutedEventArgs e) {
  55. //calling refresh after item has changed
  56. foreach(var item in Dates)
  57. item.IsChecked = false;
  58. Dates.Refresh();
  59. }
  60. }
  61. }

Result