Esempio n. 1
0
        /// <summary>
        /// RaiseAndSetIfChanged fully implements a Setter for a read-write
        /// property on a ReactiveObject, making the assumption that the
        /// property has a backing field named "_NameOfProperty". To change this
        /// assumption, set RxApp.GetFieldNameForPropertyNameFunc.
        /// </summary>
        /// <param name="property">An Expression representing the property (i.e.
        /// 'x => x.SomeProperty'</param>
        /// <param name="newValue">The new value to set the property to, almost
        /// always the 'value' keyword.</param>
        /// <returns>The newly set value, normally discarded.</returns>
        public static TRet RaiseAndSetIfChanged <TObj, TRet>(
            this TObj This,
            Expression <Func <TObj, TRet> > property,
            TRet newValue)
            where TObj : ReactiveObject
        {
            Contract.Requires(This != null);
            Contract.Requires(property != null);

            FieldInfo field;
            string    prop_name = Reflection.SimpleExpressionToPropertyName(property);

            field = Reflection.GetBackingFieldInfoForProperty <TObj>(prop_name);

            var field_val = field.GetValue(This);

            if (EqualityComparer <TRet> .Default.Equals((TRet)field_val, (TRet)newValue))
            {
                return(newValue);
            }

            This.raisePropertyChanging(prop_name);
            field.SetValue(This, newValue);
            This.raisePropertyChanged(prop_name);

            return(newValue);
        }
Esempio n. 2
0
        public IReactiveBinding <TView, TViewModel, TProp> BindCommand <TView, TViewModel, TProp, TControl, TParam>(
            TViewModel viewModel,
            TView view,
            Expression <Func <TViewModel, TProp> > propertyName,
            Expression <Func <TView, TControl> > controlName,
            Func <TParam> withParameter,
            string toEvent = null)
            where TViewModel : class
            where TView : class, IViewFor <TViewModel>
            where TProp : ICommand
        {
            var ctlName        = Reflection.SimpleExpressionToPropertyName(controlName);
            var viewPropGetter = Reflection.GetValueFetcherForProperty(typeof(TView), ctlName);

            IObservable <TProp> changed;
            IDisposable         bindingDisposable = bindCommandInternal(viewModel, view, propertyName, viewPropGetter, Observable.Empty <object>(), toEvent, out changed, cmd => {
                var rc = cmd as IReactiveCommand;
                if (rc == null)
                {
                    return(Legacy.ReactiveCommand.Create(x => cmd.CanExecute(x), _ => cmd.Execute(withParameter())));
                }

                var ret = new ReactiveCommand(rc.CanExecuteObservable);
                ret.Subscribe(_ => rc.Execute(withParameter()));
                return(ret);
            });

            return(new ReactiveBinding <TView, TViewModel, TProp>(view, viewModel, new string[] { ctlName }, new string[] { Reflection.SimpleExpressionToPropertyName(propertyName) },
                                                                  changed, BindingDirection.OneWay, bindingDisposable));
        }
Esempio n. 3
0
        /// <summary>
        /// Use this method in your ReactiveObject classes when creating custom
        /// properties where raiseAndSetIfChanged doesn't suffice.
        /// </summary>
        /// <param name="property">An Expression representing the property (i.e.
        /// 'x => x.SomeProperty'</param>
        public static void RaisePropertyChanged <TObj, TRet>(
            this TObj This,
            Expression <Func <TObj, TRet> > property)
            where TObj : ReactiveObject
        {
            var propName = Reflection.SimpleExpressionToPropertyName(property);

            This.raisePropertyChanged(propName);
        }
Esempio n. 4
0
        IDisposable bindCommandInternal <TView, TViewModel, TProp, TParam>(
            TViewModel viewModel,
            TView view,
            Expression <Func <TViewModel, TProp> > propertyName,
            Func <object, object> viewPropGetter,
            IObservable <TParam> withParameter,
            string toEvent,
            out IObservable <TProp> changed,
            Func <ICommand, ICommand> commandFixuper = null)
            where TViewModel : class
            where TView : class, IViewFor <TViewModel>
            where TProp : ICommand
        {
            var propName = Reflection.SimpleExpressionToPropertyName(propertyName);

            IDisposable disp = Disposable.Empty;

            changed = Reflection.ViewModelWhenAnyValue(viewModel, view, propertyName).Publish().RefCount();

            var propSub = changed.Subscribe(x => {
                disp.Dispose();
                if (x == null)
                {
                    disp = Disposable.Empty;
                    return;
                }

                var target = viewPropGetter(view);
                if (target == null)
                {
                    this.Log().Error("Binding {0}.{1} => {2}.{1} failed because target is null",
                                     typeof(TViewModel).FullName, propName, view.GetType().FullName);
                    disp = Disposable.Empty;
                }

                var cmd = commandFixuper != null ? commandFixuper(x) : x;
                if (toEvent != null)
                {
                    disp = CreatesCommandBinding.BindCommandToObject(cmd, target, withParameter.Select(y => (object)y), toEvent);
                }
                else
                {
                    disp = CreatesCommandBinding.BindCommandToObject(cmd, target, withParameter.Select(y => (object)y));
                }
            });

            return(Disposable.Create(() => {
                propSub.Dispose();
                disp.Dispose();
            }));
        }
Esempio n. 5
0
        public IReactiveBinding <TView, TViewModel, TProp> BindCommand <TView, TViewModel, TProp>(
            TViewModel viewModel,
            TView view,
            Expression <Func <TViewModel, TProp> > propertyName,
            string toEvent = null)
            where TViewModel : class
            where TView : class, IViewFor <TViewModel>
            where TProp : ICommand
        {
            var ctlName        = Reflection.SimpleExpressionToPropertyName(propertyName);
            var viewPropGetter = Reflection.GetValueFetcherForProperty(typeof(TView), ctlName);

            IObservable <TProp> changed;
            IDisposable         disp = bindCommandInternal(viewModel, view, propertyName, viewPropGetter, Observable.Empty <object>(), toEvent, out changed);

            return(new ReactiveBinding <TView, TViewModel, TProp>(view, viewModel, new string[] { ctlName }, new string[] { ctlName },
                                                                  changed, BindingDirection.OneWay, disp));
        }
Esempio n. 6
0
        /// <summary>
        /// Converts an Observable to an ObservableAsPropertyHelper and
        /// automatically provides the onChanged method to raise the property
        /// changed notification. The ToProperty method is semantically
        /// equivalent to this method and is often more convenient.
        /// </summary>
        /// <param name="observable">The Observable to base the property on.</param>
        /// <param name="property">An Expression representing the property (i.e.
        /// 'x => x.SomeProperty'</param>
        /// <param name="initialValue">The initial value of the property.</param>
        /// <param name="scheduler">The scheduler that the notifications will be
        /// provided on - this should normally be a Dispatcher-based scheduler
        /// (and is by default)</param>
        /// <returns>An initialized ObservableAsPropertyHelper; use this as the
        /// backing field for your property.</returns>
        public static ObservableAsPropertyHelper <TRet> ObservableToProperty <TObj, TRet>(
            this TObj This,
            IObservable <TRet> observable,
            Expression <Func <TObj, TRet> > property,
            TRet initialValue    = default(TRet),
            IScheduler scheduler = null)
            where TObj : ReactiveObject
        {
            Contract.Requires(This != null);
            Contract.Requires(observable != null);
            Contract.Requires(property != null);

            string prop_name = Reflection.SimpleExpressionToPropertyName(property);
            var    ret       = new ObservableAsPropertyHelper <TRet>(observable,
                                                                     _ => This.raisePropertyChanged(prop_name),
                                                                     initialValue, scheduler);

            LogHost.Default.Debug("OAPH {0:X} is for {1}", ret, prop_name);
            return(ret);
        }
Esempio n. 7
0
        public IReactiveBinding <TView, TViewModel, TProp> BindCommand <TView, TViewModel, TProp, TControl, TParam>(
            TViewModel viewModel,
            TView view,
            Expression <Func <TViewModel, TProp> > propertyName,
            Expression <Func <TView, TControl> > controlName,
            IObservable <TParam> withParameter,
            string toEvent = null)
            where TViewModel : class
            where TView : class, IViewFor <TViewModel>
            where TProp : ICommand
        {
            var ctlName        = Reflection.SimpleExpressionToPropertyName(controlName);
            var viewPropGetter = Reflection.GetValueFetcherForProperty(typeof(TView), ctlName);

            IObservable <TProp> changed;
            IDisposable         bindingDisposable = bindCommandInternal(viewModel, view, propertyName, viewPropGetter, withParameter, toEvent, out changed);

            return(new ReactiveBinding <TView, TViewModel, TProp>(view, viewModel, new string[] { ctlName }, Reflection.ExpressionToPropertyNames(propertyName),
                                                                  changed, BindingDirection.OneWay, bindingDisposable));
        }
Esempio n. 8
0
        /// <summary>
        /// RaiseAndSetIfChanged fully implements a Setter for a read-write
        /// property on a ReactiveObject, making the assumption that the
        /// property has a backing field named "_NameOfProperty". To change this
        /// assumption, set RxApp.GetFieldNameForPropertyNameFunc.  This
        /// overload is intended for Silverlight and WP7 where reflection
        /// cannot access the private backing field.
        /// </summary>
        /// <param name="property">An Expression representing the property (i.e.
        /// 'x => x.SomeProperty'</param>
        /// <param name="backingField">A Reference to the backing field for this
        /// property.</param>
        /// <param name="newValue">The new value to set the property to, almost
        /// always the 'value' keyword.</param>
        /// <returns>The newly set value, normally discarded.</returns>
        public static TRet RaiseAndSetIfChanged <TObj, TRet>(
            this TObj This,
            Expression <Func <TObj, TRet> > property,
            ref TRet backingField,
            TRet newValue)
            where TObj : ReactiveObject
        {
            Contract.Requires(This != null);
            Contract.Requires(property != null);

            if (EqualityComparer <TRet> .Default.Equals(backingField, newValue))
            {
                return(newValue);
            }

            string prop_name = Reflection.SimpleExpressionToPropertyName(property);

            This.raisePropertyChanging(prop_name);
            backingField = newValue;
            This.raisePropertyChanged(prop_name);
            return(newValue);
        }
Esempio n. 9
0
        /// <summary>
        /// Converts an Observable to an ObservableAsPropertyHelper and
        /// automatically provides the onChanged method to raise the property
        /// changed notification.
        /// </summary>
        /// <param name="source">The ReactiveObject that has the property</param>
        /// <param name="property">An Expression representing the property (i.e.
        /// 'x => x.SomeProperty'</param>
        /// <param name="initialValue">The initial value of the property.</param>
        /// <param name="scheduler">The scheduler that the notifications will be
        /// provided on - this should normally be a Dispatcher-based scheduler
        /// (and is by default)</param>
        /// <returns>An initialized ObservableAsPropertyHelper; use this as the
        /// backing field for your property.</returns>
        public static ObservableAsPropertyHelper <TRet> ToProperty <TObj, TRet>(
            this IObservable <TRet> This,
            TObj source,
            Expression <Func <TObj, TRet> > property,
            TRet initialValue     = default(TRet),
            IScheduler scheduler  = null,
            bool setViaReflection = true)
            where TObj : ReactiveObject
        {
            var ret = source.ObservableToProperty(This, property, initialValue, scheduler);

            string propName = Reflection.SimpleExpressionToPropertyName(property);

            if (setViaReflection)
            {
                var fi = Reflection.GetBackingFieldInfoForProperty <TObj>(propName, true);
                if (fi != null)
                {
                    fi.SetValue(source, ret);
                }
            }

            return(ret);
        }
Esempio n. 10
0
 /// <summary>
 /// RaisePropertyChanged is a helper method intended for test / mock
 /// scenarios to manually fake a property change.
 /// </summary>
 /// <param name="target">The ReactiveObject to invoke
 /// raisePropertyChanging on.</param>
 /// <param name="property">The property that will be faking a change.</param>
 public static void RaisePropertyChanged <TSender, TValue>(TSender target, Expression <Func <TSender, TValue> > property)
     where TSender : ReactiveObject
 {
     RaisePropertyChanged(target, Reflection.SimpleExpressionToPropertyName(property));
 }