Created
February 19, 2013 02:42
-
-
Save distantcam/4982662 to your computer and use it in GitHub Desktop.
RxUI Light
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reactive; | |
using System.Reactive.Linq; | |
using System.Reactive.Subjects; | |
using System.Windows.Input; | |
public class RxCommand : ICommand, IObservable<object>, IDisposable | |
{ | |
private readonly ISubject<bool> canExecuteSubject; | |
private readonly ISubject<object> executeSubject; | |
private readonly IDisposable inner; | |
private bool canExecuteLatest = true; | |
public RxCommand(IObservable<bool> canExecute = null) | |
{ | |
canExecute = canExecute ?? Observable.Return(true).Concat(Observable.Never<bool>()); | |
canExecute = canExecute.ObserveOnDispatcher(); | |
canExecuteSubject = new Subject<bool>(); | |
inner = canExecute.Subscribe(OnExecuteChanged); | |
executeSubject = new Subject<object>(); | |
} | |
public event EventHandler CanExecuteChanged; | |
public IObservable<bool> CanExecuteObservable | |
{ | |
get { return canExecuteSubject.ObserveOnDispatcher().DistinctUntilChanged(); } | |
} | |
public bool CanExecute(object parameter) | |
{ | |
return canExecuteLatest; | |
} | |
public void Execute(object parameter) | |
{ | |
executeSubject.OnNext(parameter); | |
} | |
public IDisposable Subscribe(IObserver<object> observer) | |
{ | |
return executeSubject.ObserveOnDispatcher().Subscribe( | |
Observer.Create<object>( | |
x => LogOnError(() => observer.OnNext(x)), | |
ex => LogOnError(() => observer.OnError(ex)), | |
() => LogOnError(observer.OnCompleted))); | |
} | |
public void Dispose() | |
{ | |
if (inner != null) | |
inner.Dispose(); | |
} | |
private static void LogOnError(Action action) | |
{ | |
try | |
{ | |
action(); | |
} | |
catch | |
{ | |
// Log | |
} | |
} | |
private void OnExecuteChanged(bool obj) | |
{ | |
canExecuteLatest = obj; | |
canExecuteSubject.OnNext(obj); | |
var handler = CanExecuteChanged; | |
if (handler != null) | |
handler(this, EventArgs.Empty); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ComponentModel; | |
using System.Reactive.Disposables; | |
using System.Reactive.Subjects; | |
using System.Threading; | |
public class RxObject : INotifyPropertyChanged, INotifyPropertyChanging | |
{ | |
private readonly Subject<ObservedChange> changedSubject; | |
private readonly Subject<ObservedChange> changingSubject; | |
private long changeNotificationsSuppressed = 0; | |
protected RxObject() | |
{ | |
changingSubject = new Subject<ObservedChange>(); | |
changedSubject = new Subject<ObservedChange>(); | |
} | |
public event PropertyChangedEventHandler PropertyChanged; | |
public event PropertyChangingEventHandler PropertyChanging; | |
public IObservable<ObservedChange> Changing { get { return changingSubject; } } | |
public IObservable<ObservedChange> Changed { get { return changedSubject; } } | |
public IDisposable SuppressChangeNotifications() | |
{ | |
Interlocked.Increment(ref changeNotificationsSuppressed); | |
return Disposable.Create(() => | |
Interlocked.Decrement(ref changeNotificationsSuppressed)); | |
} | |
protected void OnPropertyChanged(string propertyName) | |
{ | |
if (!ChangeNotificationsEnabled()) | |
return; | |
var handler = this.PropertyChanged; | |
if (handler != null) | |
handler(this, new PropertyChangedEventArgs(propertyName)); | |
try | |
{ | |
changedSubject.OnNext(new ObservedChange(this, propertyName)); | |
} | |
catch (Exception ex) | |
{ | |
changedSubject.OnError(ex); | |
} | |
} | |
protected void OnPropertyChanging(string propertyName) | |
{ | |
if (!ChangeNotificationsEnabled()) | |
return; | |
var handler = this.PropertyChanging; | |
if (handler != null) | |
handler(this, new PropertyChangingEventArgs(propertyName)); | |
try | |
{ | |
changingSubject.OnNext(new ObservedChange(this, propertyName)); | |
} | |
catch (Exception ex) | |
{ | |
changingSubject.OnError(ex); | |
} | |
} | |
private bool ChangeNotificationsEnabled() | |
{ | |
return Interlocked.Read(ref changeNotificationsSuppressed) == 0; | |
} | |
public struct ObservedChange | |
{ | |
public readonly string PropertyName; | |
public readonly object Sender; | |
public ObservedChange(object sender, string propertyName) | |
{ | |
Sender = sender; | |
PropertyName = propertyName; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment