|
1 |
| -# ReactiveXaml |
2 |
| - |
3 |
| -This library is an exploration I've been working on for several weeks on |
4 |
| -combining WPF Model-View-ViewModel paradigm with the Reactive Extensions for |
5 |
| -.NET (Rx). Combining these two make managing concurrency as well as expressing |
6 |
| -complicated interactions between objects possible in a declarative, functional |
7 |
| -way. Put simply, if you've ever had to chain events / callbacks together and |
8 |
| -declare state ints/booleans to keep track of what's going on, Reactive |
9 |
| -Extensions provides a sane alternative. |
10 |
| - |
11 |
| -## What's in this library |
12 |
| - |
13 |
| -``ReactiveCommand`` - an implementation of ICommand that is also a Subject whose |
14 |
| -OnNext is raised when Execute is executed. Its CanExecute can also be defined by |
15 |
| -an IObservable<bool> which means the UI will instantly update instead of |
16 |
| -implementations which rely on RequerySuggested. |
17 |
| - |
18 |
| -``ReactiveAsyncCommand`` - a derivative of ReactiveCommand that encapsulates the |
19 |
| -common pattern of "Fire asynchronous command, then marshal result back onto |
20 |
| -dispatcher thread". Allows you to set a maximum level of concurrency as well |
21 |
| -(i.e. "I only want 3 inflight requests" - when the maximum is reached, |
22 |
| -CanExecute returns false). |
23 |
| - |
24 |
| -``ReactiveObject`` - a ViewModel object based on Josh Smith's implementation, |
25 |
| -that also implements IObservable as a way to notify property changes. It also |
26 |
| -allows a straightforward way to observe the changes of a single property. |
27 |
| - |
28 |
| -``ReactiveValidatedObject`` - a derivative of ReactiveObject that is validated |
29 |
| -via DataAnnotations by implementing IDataErrorInfo, so properties can be |
30 |
| -annotated with their restrictions and the UI will automatically reflect the |
31 |
| -errors. |
32 |
| - |
33 |
| -``ObservableAsPropertyHelper<T>`` - a class that easily lets you convert an |
34 |
| -IObservable<T> into a property that stores its latest value, as well as fires |
35 |
| -NotifyPropertyChanged when the property changes. This is really useful for |
36 |
| -combining existing properties together and replacing IValueConverters, since |
37 |
| -your ViewModels will also be IObservables. |
38 |
| - |
39 |
| -``StopwatchTestScheduler`` - this class allows you to enforce time limits on |
40 |
| -items scheduled on other threads. The main use for this is in unit tests, as |
41 |
| -well as being able to say things in Debug mode like, "If any item runs in the |
42 |
| -Dispatcher scheduler for longer than 400ms that would've made the UI |
43 |
| -unresponsive, crash the application". |
44 |
| - |
45 |
| -## Blend SDK Integration |
46 |
| - |
47 |
| -``AsyncCommandVisualStateBehavior`` - this behavior will watch a |
48 |
| -ReactiveAsyncCommand and transition its target to different states based on the |
49 |
| -command's status - for example, displaying a Spinner while a command is running. |
50 |
| - |
51 |
| -``FollowObservableStateBehavior`` - this behavior will use the output of an |
52 |
| -IObservable<string> and call VisualStateManager.GoToState on its target; using |
53 |
| -Observable.Merge makes it fairly straightforward to build a state machine based |
54 |
| -on the changes in the ViewModel. |
55 |
| - |
56 |
| -``ObservableTrigger`` - this trigger will fire when an IObservable calls OnNext |
57 |
| -and can be tied to any arbitrary Expression Action. |
58 |
| - |
59 |
| -## Other stuff that's useful |
60 |
| - |
61 |
| -``MemoizingMRUCache`` - this class is non-threadsafe most recently used cache, |
62 |
| -and can be used to cache the results of expensive lookups. You provide the |
63 |
| -function to use to look up values that aren't known, then it will save the |
64 |
| -results. It also allows a "destructor" to be run when an item is released from |
65 |
| -the cache, so you can use this to manage an on-disk file cache as well (where |
66 |
| -the "Get" function downloads a file, then the "Release" function deletes it). |
67 |
| - |
68 |
| -``QueuedAsyncMRUCache`` - this class is by far the most complicated in this |
69 |
| -library, its goals are similar to MemoizingMRUCache, but instead of returning |
70 |
| -the result immediately, it will schedule a Task to run in the background and |
71 |
| -return an IObservable representing the result (a Future). Once the Future |
72 |
| -completes, its result is cached so subsequent requests will come from memory. |
73 |
| - |
74 |
| -The advantage of this class is that subsequent identical requests will block on |
75 |
| -the outstanding one (so if you ask for "foo.com" on 3 separate threads, one of |
76 |
| -them will send out the web request and the other two threads will receive the |
77 |
| -result as well). This class also allows you to place a blocking limit on the |
78 |
| -number of outstanding requests, so that further requests will block until some |
79 |
| -of the inflight requests have been satisfied. |
80 |
| - |
81 |
| -``IEnableLogger`` - this is an implementation of a simple logger that combines |
82 |
| -some of log4net's syntax with the ubiquity of the Rails logger - any class that |
83 |
| -implements the dummy IEnableLogger interface will able to access a logger for |
84 |
| -that class (i.e. `this.Log().Warn("Something bad happened!");`) |
| 1 | +# ReactiveXaml |
| 2 | + |
| 3 | +This library is an exploration I've been working on for several weeks on |
| 4 | +combining WPF Model-View-ViewModel paradigm with the Reactive Extensions for |
| 5 | +.NET (Rx). Combining these two make managing concurrency as well as expressing |
| 6 | +complicated interactions between objects possible in a declarative, functional |
| 7 | +way. Put simply, if you've ever had to chain events / callbacks together and |
| 8 | +declare state ints/booleans to keep track of what's going on, Reactive |
| 9 | +Extensions provides a sane alternative. |
| 10 | + |
| 11 | +## What's in this library |
| 12 | + |
| 13 | +``ReactiveCommand`` - an implementation of ICommand that is also a Subject whose |
| 14 | +OnNext is raised when Execute is executed. Its CanExecute can also be defined by |
| 15 | +an IObservable<bool> which means the UI will instantly update instead of |
| 16 | +implementations which rely on RequerySuggested. |
| 17 | + |
| 18 | +``ReactiveAsyncCommand`` - a derivative of ReactiveCommand that encapsulates the |
| 19 | +common pattern of "Fire asynchronous command, then marshal result back onto |
| 20 | +dispatcher thread". Allows you to set a maximum level of concurrency as well |
| 21 | +(i.e. "I only want 3 inflight requests" - when the maximum is reached, |
| 22 | +CanExecute returns false). |
| 23 | + |
| 24 | +``ReactiveObject`` - a ViewModel object based on Josh Smith's implementation, |
| 25 | +that also implements IObservable as a way to notify property changes. It also |
| 26 | +allows a straightforward way to observe the changes of a single property. |
| 27 | + |
| 28 | +``ReactiveValidatedObject`` - a derivative of ReactiveObject that is validated |
| 29 | +via DataAnnotations by implementing IDataErrorInfo, so properties can be |
| 30 | +annotated with their restrictions and the UI will automatically reflect the |
| 31 | +errors. |
| 32 | + |
| 33 | +``ObservableAsPropertyHelper<T>`` - a class that easily lets you convert an |
| 34 | +IObservable<T> into a property that stores its latest value, as well as fires |
| 35 | +NotifyPropertyChanged when the property changes. This is really useful for |
| 36 | +combining existing properties together and replacing IValueConverters, since |
| 37 | +your ViewModels will also be IObservables. |
| 38 | + |
| 39 | +``StopwatchTestScheduler`` - this class allows you to enforce time limits on |
| 40 | +items scheduled on other threads. The main use for this is in unit tests, as |
| 41 | +well as being able to say things in Debug mode like, "If any item runs in the |
| 42 | +Dispatcher scheduler for longer than 400ms that would've made the UI |
| 43 | +unresponsive, crash the application". |
| 44 | + |
| 45 | +## Blend SDK Integration |
| 46 | + |
| 47 | +``AsyncCommandVisualStateBehavior`` - this behavior will watch a |
| 48 | +ReactiveAsyncCommand and transition its target to different states based on the |
| 49 | +command's status - for example, displaying a Spinner while a command is running. |
| 50 | + |
| 51 | +``FollowObservableStateBehavior`` - this behavior will use the output of an |
| 52 | +IObservable<string> and call VisualStateManager.GoToState on its target; using |
| 53 | +Observable.Merge makes it fairly straightforward to build a state machine based |
| 54 | +on the changes in the ViewModel. |
| 55 | + |
| 56 | +``ObservableTrigger`` - this trigger will fire when an IObservable calls OnNext |
| 57 | +and can be tied to any arbitrary Expression Action. |
| 58 | + |
| 59 | +## Other stuff that's useful |
| 60 | + |
| 61 | +``MemoizingMRUCache`` - this class is non-threadsafe most recently used cache, |
| 62 | +and can be used to cache the results of expensive lookups. You provide the |
| 63 | +function to use to look up values that aren't known, then it will save the |
| 64 | +results. It also allows a "destructor" to be run when an item is released from |
| 65 | +the cache, so you can use this to manage an on-disk file cache as well (where |
| 66 | +the "Get" function downloads a file, then the "Release" function deletes it). |
| 67 | + |
| 68 | +``QueuedAsyncMRUCache`` - this class is by far the most complicated in this |
| 69 | +library, its goals are similar to MemoizingMRUCache, but instead of returning |
| 70 | +the result immediately, it will schedule a Task to run in the background and |
| 71 | +return an IObservable representing the result (a Future). Once the Future |
| 72 | +completes, its result is cached so subsequent requests will come from memory. |
| 73 | + |
| 74 | +The advantage of this class is that subsequent identical requests will block on |
| 75 | +the outstanding one (so if you ask for "foo.com" on 3 separate threads, one of |
| 76 | +them will send out the web request and the other two threads will receive the |
| 77 | +result as well). This class also allows you to place a blocking limit on the |
| 78 | +number of outstanding requests, so that further requests will block until some |
| 79 | +of the inflight requests have been satisfied. |
| 80 | + |
| 81 | +``IEnableLogger`` - this is an implementation of a simple logger that combines |
| 82 | +some of log4net's syntax with the ubiquity of the Rails logger - any class that |
| 83 | +implements the dummy IEnableLogger interface will able to access a logger for |
| 84 | +that class (i.e. `this.Log().Warn("Something bad happened!");`) |
0 commit comments