BindableBase.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System.Collections.Generic;
  2. using System.ComponentModel;
  3. using System.Runtime.CompilerServices;
  4. using System;
  5. namespace HandyControl.Interactivity.Commands
  6. {
  7. /// <summary>
  8. /// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
  9. /// </summary>
  10. public abstract class BindableBase : INotifyPropertyChanged
  11. {
  12. /// <summary>
  13. /// Occurs when a property value changes.
  14. /// </summary>
  15. public event PropertyChangedEventHandler PropertyChanged;
  16. /// <summary>
  17. /// Checks if a property already matches a desired value. Sets the property and
  18. /// notifies listeners only when necessary.
  19. /// </summary>
  20. /// <typeparam name="T">Type of the property.</typeparam>
  21. /// <param name="storage">Reference to a property with both getter and setter.</param>
  22. /// <param name="value">Desired value for the property.</param>
  23. /// <param name="propertyName">Name of the property used to notify listeners. This
  24. /// value is optional and can be provided automatically when invoked from compilers that
  25. /// support CallerMemberName.</param>
  26. /// <returns>True if the value was changed, false if the existing value matched the
  27. /// desired value.</returns>
  28. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  29. {
  30. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  31. storage = value;
  32. RaisePropertyChanged(propertyName);
  33. return true;
  34. }
  35. /// <summary>
  36. /// Checks if a property already matches a desired value. Sets the property and
  37. /// notifies listeners only when necessary.
  38. /// </summary>
  39. /// <typeparam name="T">Type of the property.</typeparam>
  40. /// <param name="storage">Reference to a property with both getter and setter.</param>
  41. /// <param name="value">Desired value for the property.</param>
  42. /// <param name="propertyName">Name of the property used to notify listeners. This
  43. /// value is optional and can be provided automatically when invoked from compilers that
  44. /// support CallerMemberName.</param>
  45. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  46. /// <returns>True if the value was changed, false if the existing value matched the
  47. /// desired value.</returns>
  48. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  49. {
  50. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  51. storage = value;
  52. onChanged?.Invoke();
  53. RaisePropertyChanged(propertyName);
  54. return true;
  55. }
  56. /// <summary>
  57. /// Raises this object's PropertyChanged event.
  58. /// </summary>
  59. /// <param name="propertyName">Name of the property used to notify listeners. This
  60. /// value is optional and can be provided automatically when invoked from compilers
  61. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  62. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  63. {
  64. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  65. }
  66. /// <summary>
  67. /// Raises this object's PropertyChanged event.
  68. /// </summary>
  69. /// <param name="args">The PropertyChangedEventArgs</param>
  70. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  71. {
  72. PropertyChanged?.Invoke(this, args);
  73. }
  74. }
  75. }