-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathINotifyPropertyChangedSample.linq
137 lines (120 loc) · 4.96 KB
/
INotifyPropertyChangedSample.linq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<Query Kind="Program">
<Reference><RuntimeDirectory>\System.Runtime.dll</Reference>
<Reference><RuntimeDirectory>\System.Threading.Tasks.dll</Reference>
<NuGetReference>Rx-Main</NuGetReference>
<Namespace>System.ComponentModel</Namespace>
<Namespace>System.Reactive.Disposables</Namespace>
<Namespace>System.Reactive.Linq</Namespace>
</Query>
void Main()
{
var Dave = new Person();
Dave.PropertyChanged+=(s,e)=>{e.PropertyName.Dump("PropertyChanged");};
Dave.OnAnyPropertyChanges().Dump("OnAnyPropertyChanges");
Dave.OnPropertyChanges(d=>d.Name).Dump("OnPropertyChanges");
Dave.Name = "Dave";
Dave.Age = 21;
}
// Define other methods and classes here
public class Person : INotifyPropertyChanged
{
string _name;
int _age;
public string Name
{
get { return _name; }
set
{
if(_name !=value)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
public int Age
{
get { return _age; }
set
{
if(_age !=value)
{
_age = value;
OnPropertyChanged("Age");
}
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public static class NotificationExtensions
{
/// <summary>
/// Returns an observable sequence of the source any time the <c>PropertyChanged</c> event is raised.
/// </summary>
/// <typeparam name="T">The type of the source object. Type must implement <seealso cref="INotifyPropertyChanged"/>.</typeparam>
/// <param name="source">The object to observe property changes on.</param>
/// <returns>Returns an observable sequence of the value of the source when ever the <c>PropertyChanged</c> event is raised.</returns>
public static IObservable<T> OnAnyPropertyChanges<T>(this T source)
where T : INotifyPropertyChanged
{
return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => handler.Invoke,
h => source.PropertyChanged += h,
h => source.PropertyChanged -= h)
.Select(_=>source);
}
/// <summary>
/// Returns an observable sequence of the value of a property when <paramref name="source"/> raises <seealso cref="INotifyPropertyChanged.PropertyChanged"/> for the given property.
/// </summary>
/// <typeparam name="T">The type of the source object. Type must implement <seealso cref="INotifyPropertyChanged"/>.</typeparam>
/// <typeparam name="TProperty">The type of the property that is being observed.</typeparam>
/// <param name="source">The object to observe property changes on.</param>
/// <param name="property">An expression that describes which property to observe.</param>
/// <returns>Returns an observable sequence of the property values as they change.</returns>
public static IObservable<TProperty> OnPropertyChanges<T, TProperty>(this T source, Expression<Func<T, TProperty>> property)
where T : INotifyPropertyChanged
{
return Observable.Create<TProperty>(o=>
{
var propertyName = property.GetPropertyInfo().Name;
var propertySelector = property.Compile();
return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => handler.Invoke,
h => source.PropertyChanged += h,
h => source.PropertyChanged -= h)
.Where(e=>e.EventArgs.PropertyName==propertyName)
.Select(e=>propertySelector(source))
.Subscribe(o);
});
}
}
public static class PropertyExtensions
{
/// <summary>
/// Gets property information for the specified <paramref name="property"/> expression.
/// </summary>
/// <typeparam name="TSource">Type of the parameter in the <paramref name="property"/> expression.</typeparam>
/// <typeparam name="TValue">Type of the property's value.</typeparam>
/// <param name="property">The expression from which to retrieve the property information.</param>
/// <returns>Property information for the specified expression.</returns>
/// <exception cref="ArgumentException">The expression is not understood.</exception>
public static PropertyInfo GetPropertyInfo<TSource, TValue>(this Expression<Func<TSource, TValue>> property)
{
if (property == null)
throw new ArgumentNullException("property");
var body = property.Body as MemberExpression;
if (body == null)
throw new ArgumentException("Expression is not a property", "property");
var propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("Expression is not a property", "property");
return propertyInfo;
}
}