PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/ShanghaiFilmCenters-R1.2/packages/MVVM-Sidekick.1.2.0.0/src/CodeFiles/Reactive.cs

https://github.com/lulee007/WP-ShanghaiFilmCenters
C# | 406 lines | 290 code | 73 blank | 43 comment | 2 complexity | 4c213c5d45ef75556a2c02df00affe89 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Text;
  5using System.ComponentModel;
  6using System.Linq.Expressions;
  7using System.Runtime.Serialization;
  8using System.Reflection;
  9using System.Threading.Tasks;
 10using System.Threading;
 11using System.Windows.Input;
 12using MVVMSidekick.ViewModels;
 13using MVVMSidekick.Commands;
 14using System.Runtime.CompilerServices;
 15using MVVMSidekick.Reactive;
 16using System.Reactive.Linq;
 17using System.Reactive.Subjects;
 18using System.Reactive;
 19using System.Reactive.Threading.Tasks;
 20using MVVMSidekick.EventRouting;
 21using System.Collections.ObjectModel;
 22using System.Collections.Specialized;
 23using System.IO;
 24using System.Collections;
 25using MVVMSidekick.Utilities;
 26#if NETFX_CORE
 27using Windows.UI.Xaml;
 28using Windows.UI.Xaml.Data;
 29using Windows.UI.Xaml.Controls;
 30using System.Collections.Concurrent;
 31using Windows.UI.Xaml.Navigation;
 32
 33using Windows.UI.Xaml.Controls.Primitives;
 34
 35#elif WPF
 36using System.Windows;
 37using System.Windows.Controls;
 38using System.Windows.Data;
 39using System.Collections.Concurrent;
 40using System.Windows.Navigation;
 41
 42using MVVMSidekick.Views;
 43using System.Windows.Controls.Primitives;
 44using MVVMSidekick.Utilities;
 45
 46#elif SILVERLIGHT_5||SILVERLIGHT_4
 47using System.Windows;
 48using System.Windows.Controls;
 49using System.Windows.Data;
 50using System.Windows.Navigation;
 51using System.Windows.Controls.Primitives;
 52#elif WINDOWS_PHONE_8||WINDOWS_PHONE_7
 53using System.Windows;
 54using System.Windows.Controls;
 55using Microsoft.Phone.Controls;
 56using System.Windows.Data;
 57using System.Windows.Navigation;
 58using System.Windows.Controls.Primitives;
 59#endif
 60
 61
 62namespace MVVMSidekick
 63{
 64    namespace Reactive
 65    {
 66
 67        public static class EventTuple
 68        {
 69            public static EventTuple<TSource, TEventArgs> Create<TSource, TEventArgs>(TSource source, TEventArgs eventArgs)
 70            {
 71                return new EventTuple<TSource, TEventArgs> { Source = source, EventArgs = eventArgs };
 72            }
 73
 74        }
 75        public struct EventTuple<TSource, TEventArgs>
 76        {
 77            public TSource Source { get; set; }
 78            public TEventArgs EventArgs { get; set; }
 79        }
 80
 81        public static class MVVMRxExtensions
 82        {
 83
 84            //public static IDisposable SubscribeToRouter(this IObservable<Task> executionSequence, BindableBase model, string eventName, CallingCodeContext callingCodeContext)
 85            //{
 86            //    EventRouting.EventRouter.Instance.GetEventObject<TaskExecutionWindowEventArg>().RaiseEvent(model, eventName, callingCodeContext);
 87            //    return executionSequence.Subscribe();
 88
 89            //}
 90
 91            /// <summary>
 92            /// Register a Do action to the observer, Notify the value in this sequence to EventRouter
 93            /// </summary>
 94            /// <typeparam name="T">Sequence Value Type</typeparam>
 95            /// <param name="sequence">value sequence</param>
 96            /// <param name="eventRounter"> target </param>
 97            /// <param name="source">value source</param>
 98            /// <param name="registerName">log name</param>
 99            /// <returns>same value sequence inputed</returns>
100            public static IObservable<T> DoNotifyEventRouter<T>(this IObservable<T> sequence, EventRouter eventRounter, object source = null, [CallerMemberName] string registerName = null)
101            {
102                return
103                    sequence.Do(
104                            v => eventRounter.RaiseEvent(source, v, registerName)
105
106                        );
107
108            }
109
110            /// <summary>
111            /// Register a Do action to the observer, Notify the value in this sequence to EventRouter
112            /// </summary>
113            /// <typeparam name="T">Sequence Value Type</typeparam>
114            /// <param name="sequence">value sequence</param>
115            /// <param name="source">value source</param>
116            /// <param name="registerName">log name</param>
117            /// <returns>same value sequence inputed</returns>
118            public static IObservable<T> DoNotifyDefaultEventRouter<T>(this IObservable<T> sequence, object source = null, [CallerMemberName] string registerName = null)
119            {
120                return DoNotifyEventRouter(sequence, EventRouter.Instance, source, registerName);
121            }
122
123
124
125            public static IObservable<Task<Tout>> DoExecuteUIBusyTask<Tin, Tout>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, CancellationToken, Task<Tout>> taskBody, CancellationToken cancellationToken)
126            {
127                return sequence.Select
128                    (
129                        inContext => vm.ExecuteTask(taskBody, inContext, cancellationToken, true)
130                    );
131            }
132
133            public static IObservable<Task<Tout>> DoExecuteUITask<Tin, Tout>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, CancellationToken, Task<Tout>> taskBody, CancellationToken cancellationToken)
134            {
135                return sequence.Select
136                    (
137                        inContext => vm.ExecuteTask(taskBody, inContext, cancellationToken, false)
138                    );
139            }
140            public static IObservable<Task> DoExecuteUIBusyTask<Tin>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, CancellationToken, Task> taskBody, CancellationToken cancellationToken)
141            {
142                return sequence.Select
143                (
144                    inContext => vm.ExecuteTask(taskBody, inContext, cancellationToken, true)
145                );
146            }
147
148            public static IObservable<Task> DoExecuteUITask<Tin>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, CancellationToken, Task> taskBody, CancellationToken cancellationToken)
149            {
150                return sequence.Select
151               (
152                   inContext => vm.ExecuteTask(taskBody, inContext, cancellationToken, false)
153               );
154            }
155
156
157
158
159
160            public static IObservable<Task<Tout>> DoExecuteUIBusyTask<Tin, Tout>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, Task<Tout>> taskBody)
161            {
162                return sequence.Select
163                    (
164                        inContext => vm.ExecuteTask(taskBody, inContext, true)
165                    );
166            }
167
168            public static IObservable<Task<Tout>> DoExecuteUITask<Tin, Tout>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, Task<Tout>> taskBody)
169            {
170                return sequence.Select
171                    (
172                        inContext => vm.ExecuteTask(taskBody, inContext, false)
173                    );
174            }
175            public static IObservable<Task> DoExecuteUIBusyTask<Tin>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, Task> taskBody)
176            {
177                return sequence.Select
178                (
179                    inContext => vm.ExecuteTask(taskBody, inContext, true)
180                );
181            }
182
183            public static IObservable<Task> DoExecuteUITask<Tin>(this IObservable<Tin> sequence, IViewModel vm, Func<Tin, Task> taskBody)
184            {
185                return sequence.Select
186               (
187                   inContext => vm.ExecuteTask(taskBody, inContext, false)
188               );
189            }
190
191            /// <summary>
192            /// <para>Create a instance of IObservable that fires when property changed event is raised.</para>
193            /// <para>创建一个监视属性变化事件观察者IObservable实例。</para>
194            /// </summary>
195            /// <returns></returns>
196            public static IObservable<EventPattern<PropertyChangedEventArgs>> CreatePropertyChangedObservable(this BindableBase bindable)
197            {
198                return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
199                        eh => bindable.PropertyChanged += eh,
200                        eh => bindable.PropertyChanged -= eh
201                    )
202                    .Where(_ => bindable.IsNotificationActivated);
203            }
204
205
206            public static IObservable<EventPattern<NotifyCollectionChangedEventArgs>> GetEventObservable<T>(this ObservableCollection<T> source, BindableBase model)
207            {
208                var rval = Observable
209                  .FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
210                      (
211                          ev => source.CollectionChanged += ev,
212                          ev => source.CollectionChanged -= ev
213                      ).Where(_ => model.IsNotificationActivated);
214                return rval;
215            }
216            public static IObservable<EventTuple<ValueContainer<TValue>, TValue>> GetNewValueObservable<TValue>
217                (
218                    this ValueContainer<TValue> source
219
220                )
221            {
222
223                return Observable.FromEventPattern<EventHandler<ValueChangedEventArgs<TValue>>, ValueChangedEventArgs<TValue>>(
224                        eh => source.ValueChanged += eh,
225                        eh => source.ValueChanged -= eh)
226                        .Select(
227                            x => EventTuple.Create(source, x.EventArgs.NewValue)
228
229                        );
230
231            }
232
233            public static IObservable<EventTuple<ValueContainer<TValue>, ValueChangedEventArgs<TValue>>>
234                GetEventObservable<TValue>(this ValueContainer<TValue> source)
235            {
236
237                var eventArgSeq = Observable.FromEventPattern<EventHandler<ValueChangedEventArgs<TValue>>, ValueChangedEventArgs<TValue>>(
238                        eh => source.ValueChanged += eh,
239                        eh => source.ValueChanged -= eh);
240                return eventArgSeq.Select(
241                            x => EventTuple.Create(source, x.EventArgs)
242                        );
243                ;
244            }
245
246
247            public static IObserver<TValue> AsObserver<TValue>(this ValueContainer<TValue> source)
248            {
249                return Observer.Create<TValue>(v => source.SetValueAndTryNotify(v));
250
251            }
252
253
254            public static IObservable<object> GetNullObservable<TValue>(this ValueContainer<TValue> source)
255            {
256
257                var eventArgSeq = Observable.FromEventPattern<EventHandler<ValueChangedEventArgs<TValue>>, ValueChangedEventArgs<TValue>>(
258                        eh => source.ValueChanged += eh,
259                        eh => source.ValueChanged -= eh);
260                return eventArgSeq.Select(
261                            x => null as object
262                        );
263                ;
264            }
265            /// <summary>
266            /// 转化
267            /// </summary>
268            /// <typeparam name="TEventArgs"></typeparam>
269            /// <param name="source"></param>
270            /// <returns></returns>
271            [Obsolete("The source is already  IObservable<RouterEventData<TEventArgs>>")]
272            public static IObservable<RouterEventData<TEventArgs>>
273                GetRouterEventObservable<TEventArgs>(this MVVMSidekick.EventRouting.EventRouter.EventObject<TEventArgs> source)
274#if !NETFX_CORE
275 where TEventArgs : EventArgs
276#endif
277            {
278
279
280                return source;
281
282            }
283            /// <summary>
284            /// Bind Command to IsUIBusy property.
285            /// </summary>
286            /// <typeparam name="TCommand">A sub class of ReactiveCommand</typeparam>
287            /// <typeparam name="TResource">The resource type of CommandModel</typeparam>
288            /// <typeparam name="TViewModel">The View Model type command wanna bind to</typeparam>
289            /// <param name="command">Command itself</param>
290            /// <param name="model">The View Model  command wanna bind to</param>
291            /// <returns>command instance itself</returns>
292            public static CommandModel<TCommand, TResource> ListenToIsUIBusy<TCommand, TResource, TViewModel>(this CommandModel<TCommand, TResource> command, ViewModelBase<TViewModel> model, bool canExecuteWhenBusy = false)
293                where TViewModel : ViewModelBase<TViewModel>
294                where TCommand : ReactiveCommand
295            {
296
297                //See Test  CommandListenToUIBusy_Test
298                model.GetValueContainer(x => x.IsUIBusy).GetNewValueObservable()
299                  .Select(e =>
300                      !(canExecuteWhenBusy ^ e.EventArgs))
301                  .Subscribe(command.CommandCore.CanExecuteObserver)
302                  .DisposeWith(model);
303
304                return command;
305            }
306
307        }
308
309        public class ReactiveCommand : EventCommandBase, ICommand, IObservable<EventPattern<EventCommandEventArgs>>
310        {
311
312
313
314            protected Lazy<IObservable<EventPattern<EventCommandEventArgs>>> _LazyObservableExecute;
315            protected Lazy<IObserver<bool>> _LazyObserverCanExecute;
316            protected bool _CurrentCanExecuteObserverValue;
317
318            protected ReactiveCommand()
319            {
320                ConfigReactive();
321
322            }
323
324            public ReactiveCommand(bool canExecute = false)
325                : this()
326            {
327                _CurrentCanExecuteObserverValue = canExecute;
328            }
329
330
331            virtual protected void ConfigReactive()
332            {
333                _LazyObservableExecute = new Lazy<IObservable<EventPattern<EventCommandEventArgs>>>
334                (
335                    () =>
336                    {
337                        var ob = Observable.FromEventPattern<EventHandler<EventCommandEventArgs>, EventCommandEventArgs>
338                    (
339                        eh =>
340                        {
341                            this.CommandExecute += eh;
342                        },
343                        eh =>
344                        {
345                            this.CommandExecute -= eh;
346                        }
347                    );
348
349                        return ob;
350                    }
351                );
352
353                _LazyObserverCanExecute = new Lazy<IObserver<bool>>
354                (
355                    () =>
356                        Observer.Create<bool>(
357                        canExe =>
358                        {
359                            var oldv = this._CurrentCanExecuteObserverValue;
360                            _CurrentCanExecuteObserverValue = canExe;
361                            if (oldv != canExe)
362                            {
363                                OnCanExecuteChanged();
364                            }
365                        }
366                        )
367
368                );
369            }
370            public IObserver<bool> CanExecuteObserver { get { return _LazyObserverCanExecute.Value; } }
371
372            public override bool CanExecute(object parameter)
373            {
374                return _CurrentCanExecuteObserverValue;
375            }
376
377
378
379
380
381
382            public IDisposable Subscribe(IObserver<EventPattern<EventCommandEventArgs>> observer)
383            {
384                return _LazyObservableExecute
385                      .Value
386                      .Subscribe(observer);
387            }
388        }
389
390
391        public class TaskExecutionWindowEventArg : EventArgs
392        {
393
394            public TaskExecutionWindowEventArg(Task executedTask, CallingCodeContext callingContext)
395            {
396                TaskWindow = executedTask.ToObservable();
397                CallingCodeContext = callingContext;
398            }
399
400            public IObservable<Unit> TaskWindow { get; private set; }
401            public CallingCodeContext CallingCodeContext { get; private set; }
402
403        }
404
405    }
406}