Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixing problem with exception not being pushed to OnError method.

  • Loading branch information...
commit 60982dcad9481f1d1a9585b1a429bf4cc702ecf3 1 parent b8b0d24
StanislawSwierc authored
3  CodeBinding.Rx/CodeBinding.Rx.csproj
View
@@ -42,6 +42,9 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="ObservableValueConverter.cs" />
+ <Compile Include="ObservableValueConverterBase.cs" />
+ <Compile Include="ObservableMultiValueConverter.cs" />
<Compile Include="ObservableBindingTarget.cs" />
<Compile Include="ObservableEx.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
50 CodeBinding.Rx/ObservableEx.cs
View
@@ -29,16 +29,56 @@ public static IObservable<TResult> Create<TResult>(Expression<Func<TResult>> exp
// Create binding
var binding = BindingEx.FromExpression(expression);
+ IObservable<TResult> observableConverter = null;
+ if (binding is Binding)
+ {
+ var single = (Binding)binding;
+ if (single.Converter != null)
+ {
+ // Create intercepting converter
+ var converter = new ObservableValueConverter<TResult>(single.Converter);
+ // Replace original converter
+ single.Converter = converter;
+ observableConverter = converter;
+ }
+ }
+ else if (binding is MultiBinding)
+ {
+ var multi = (MultiBinding)binding;
+ // Create intercepting converter
+ var converter = new ObservableMultiValueConverter<TResult>(multi.Converter);
+ // Replace original converter
+ multi.Converter = converter;
+ observableConverter = converter;
+ }
+ else
+ {
+ // Only Binding and MultiBinding classes are supported
+ throw new InvalidOperationException("Invalid binding type");
+ }
return Observable.Create<TResult>(observer =>
{
// Create target object
var target = new ObservableBindingTarget<TResult>();
- target.SetBinding(ObservableBindingTarget<TResult>.ValueProperty, binding);
- return new CompositeDisposable(
- target.Subscribe(observer),
- target
- );
+ if (observableConverter != null)
+ {
+ var subscription = observableConverter.Subscribe(observer);
+ // Binding has to be set in order to enable converter
+ target.SetBinding(ObservableBindingTarget<TResult>.ValueProperty, binding);
+ return new CompositeDisposable(
+ target,
+ subscription
+ );
+ }
+ else
+ {
+ target.SetBinding(ObservableBindingTarget<TResult>.ValueProperty, binding);
+ return new CompositeDisposable(
+ target.Subscribe(observer),
+ target
+ );
+ }
}
);
}
46 CodeBinding.Rx/ObservableMultiValueConverter.cs
View
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+using System.Windows;
+using System.Reactive.Disposables;
+using System.Diagnostics.Contracts;
+
+namespace CodeBinding.Rx
+{
+ internal class ObservableMultiValueConverter<T> : ObservableValueConverterBase<T>, IMultiValueConverter
+ {
+ private IMultiValueConverter m_Inner;
+
+ public ObservableMultiValueConverter(IMultiValueConverter converter)
+ {
+ Contract.Requires(converter != null);
+
+ m_Inner = converter;
+ }
+
+ #region IMultiValueConverter Implementation
+
+ public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ try
+ {
+ object result = m_Inner.Convert(values, targetType, parameter, culture);
+ SendNext((T)result);
+ }
+ catch (Exception ex)
+ {
+ SendError(ex);
+ }
+ return DependencyProperty.UnsetValue;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new InvalidOperationException();
+ }
+
+ #endregion
+ }
+}
46 CodeBinding.Rx/ObservableValueConverter.cs
View
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+using System.Windows;
+using System.Reactive.Disposables;
+using System.Diagnostics.Contracts;
+
+namespace CodeBinding.Rx
+{
+ internal class ObservableValueConverter<T> : ObservableValueConverterBase<T>, IValueConverter
+ {
+ private IValueConverter m_Inner;
+
+ public ObservableValueConverter(IValueConverter converter)
+ {
+ Contract.Requires(converter != null);
+
+ m_Inner = converter;
+ }
+
+ #region IValueConverter Implementation
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ try
+ {
+ object result = m_Inner.Convert(value, targetType, parameter, culture);
+ SendNext((T)result);
+ }
+ catch (Exception ex)
+ {
+ SendError(ex);
+ }
+ return DependencyProperty.UnsetValue;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
71 CodeBinding.Rx/ObservableValueConverterBase.cs
View
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+using System.Windows;
+using System.Reactive.Disposables;
+using System.Diagnostics.Contracts;
+
+namespace CodeBinding.Rx
+{
+ internal abstract class ObservableValueConverterBase<T> : IObservable<T>
+ {
+ private Action<T> m_OnNext;
+ private Action<Exception> m_OnError;
+
+ protected void SendNext(T value)
+ {
+ var handler = m_OnNext;
+ if (handler != null)
+ {
+ handler(value);
+ }
+ }
+
+ protected void SendError(Exception error)
+ {
+ Action<Exception> handler = null;
+ lock (this)
+ {
+ // Save current subscribers
+ handler = m_OnError;
+
+ // Remove all subscribers
+ m_OnError = null;
+ m_OnNext = null;
+
+ }
+ if (handler != null)
+ {
+ handler(error);
+ }
+ }
+
+ public IDisposable Subscribe(IObserver<T> observer)
+ {
+ Contract.Requires(observer != null);
+
+ // Lock to make sure m_OnNext and m_OnError are managed together
+ lock (this)
+ {
+ m_OnNext += observer.OnNext;
+ m_OnError += observer.OnError;
+ }
+
+ return Disposable.Create(() =>
+ {
+ // Check if handlers have been cleared already
+ if (m_OnError != null)
+ {
+ lock (this)
+ {
+ m_OnNext -= observer.OnNext;
+ m_OnError -= observer.OnError;
+ }
+ }
+ }
+ );
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.