/// <summary> /// <para>Create a new Value Container</para> /// <para>创建属性值容器</para> /// </summary> /// <param name="info">Property name/属性名</param> /// <param name="model"><para>The model that Value Container will be held with.</para> /// <para>所属的model实例</para></param> /// <param name="initValue">The first value of this container/初始值</param> public ValueContainer(string info, BindableBase model, TProperty initValue = default(TProperty)) : this(info, model, (v1, v2) => { if (v1 == null) { if (v2 == null) { return(true); } else { return(false); } } else if (v2 == null) { return(false); } else { return(v1.Equals(v2)); } }, initValue) { }
/// <summary> /// Internals the property change. /// </summary> /// <param name="modelInstance">The model instance.</param> /// <param name="newValue">The new value.</param> /// <param name="message">The message.</param> private async void InternalPropertyChange(BindableBase modelInstance, TProperty newValue, string message) { //find out there will be a changing by makesure they are not equal var changing = (this.EqualityComparer != null) ? !this.EqualityComparer(newValue, _value) : !Object.Equals(newValue, _value); if (!changing) { return; } //fire changing event ask if anyone against changing var changingArg = new ValueChangingEventArgs <TProperty>(message, _value, newValue); modelInstance.RaisePropertyChanging(changingArg); var oldvalue = _value; _value = newValue; await Task.Yield(); if (changingArg.Cancellation.IsCancellationRequested) { _value = oldvalue; return; } if (ValueChanging != null) { ValueChanging.Invoke(this, changingArg); await Task.Yield(); if (changingArg.Cancellation.IsCancellationRequested) { _value = oldvalue; return; } } if (NonGenericValueChanging != null) { NonGenericValueChanging.Invoke(this, changingArg); await Task.Yield(); if (changingArg.Cancellation.IsCancellationRequested) { _value = oldvalue; return; } } ValueChangedEventArgs <TProperty> changedArg = new ValueChangedEventArgs <TProperty>(message, oldvalue, newValue); modelInstance.RaisePropertyChanged(changedArg); ValueChanged?.Invoke(this, changedArg); NonGenericValueChanged?.Invoke(this, changedArg); }
/// <summary> /// Internals the property change. /// </summary> /// <param name="objectInstance">The object instance.</param> /// <param name="newValue">The new value.</param> /// <param name="currentValue">The current value.</param> /// <param name="message">The message.</param> private void InternalPropertyChange(BindableBase objectInstance, TProperty newValue, ref TProperty currentValue, string message) { var changing = (this.EqualityComparer != null) ? !this.EqualityComparer(newValue, currentValue) : !Object.Equals(newValue, currentValue); if (changing) { var oldvalue = currentValue; currentValue = newValue; ValueChangedEventArgs <TProperty> arg = null; Func <PropertyChangedEventArgs> lzf = () => { arg = arg ?? new ValueChangedEventArgs <TProperty>(message, oldvalue, newValue); return(arg); }; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(message)); objectInstance.RaisePropertyChanged(lzf); ValueChanged?.Invoke(this, lzf() as ValueChangedEventArgs <TProperty>); ValueChangedWithNameOnly?.Invoke(this, new PropertyChangedEventArgs(message)); ValueChangedWithNothing?.Invoke(this, EventArgs.Empty); } }
/// <summary> /// Initializes the specified property name. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="model">The model.</param> /// <param name="propertyName">Name of the property.</param> /// <param name="reference">The reference.</param> /// <param name="locator">The locator.</param> /// <param name="defaultValueFactory">The default value factory.</param> /// <returns>ValueContainer<T>.</returns> public static ValueContainer <T> Initialize <T>(this BindableBase model, string propertyName, ref Property <T> reference, ref Func <BindableBase, ValueContainer <T> > locator, Func <T> defaultValueFactory = null) { if (reference == null) { reference = new Property <T>(locator); } if (reference.Container == null) { reference.Container = new ValueContainer <T>(propertyName, model); if (defaultValueFactory != null) { reference.Container.Value = defaultValueFactory(); } } return(reference.Container); }
/// <summary> /// <para>Create a new Value Container</para> /// <para>创建属性值容器</para> /// </summary> /// <param name="info">Property name/属性名</param> /// <param name="model"><para>The model that Value Container will be held with.</para> /// <para>所属的model实例</para></param> /// <param name="equalityComparer"><para>Comparer of new/old value, for notifition.</para> /// <para>判断两个值是否相等的比较器,用于判断是否通知变更</para></param> /// <param name="initValue">The first value of this container/初始值</param> public ValueContainer(string info, BindableBase model, Func <TProperty, TProperty, bool> equalityComparer, TProperty initValue = default(TProperty)) { EqualityComparer = equalityComparer; PropertyName = info; PropertyType = typeof(TProperty); Model = model; Value = initValue; _Errors = new ObservableCollection <ErrorEntity>(); _Errors.GetEventObservable(model) .Subscribe ( e => { model.RaiseErrorsChanged(PropertyName); } ) .DisposeWith(model); }
/// <summary> /// <para>Cast a model instance to current model subtype</para> /// <para>将一个 model 引用特化为本子类型的引用</para> /// </summary> /// <param name="model">some bindable model/某种可绑定model</param> /// <returns>Current sub type instance/本类型引用</returns> public static TSubClassType CastToCurrentType(BindableBase model) { return((TSubClassType)model); }
/// <summary> /// Gets the or create plain locator. /// </summary> /// <param name="colName">Name of the col.</param> /// <param name="viewModel">The view model.</param> /// <returns>Func<TSubClassType, IValueContainer>.</returns> private static Func <TSubClassType, IValueContainer> GetOrCreatePlainLocator(string colName, BindableBase viewModel) { Func <TSubClassType, IValueContainer> pf; if (!_plainPropertyContainerGetters.TryGetValue(colName, out pf)) { var p = new ValueContainer <object>(colName, viewModel); Func <TSubClassType, ValueContainer <object> > tpf = _ => p; pf = tpf; _plainPropertyContainerGetters[colName] = pf; //TypeDic<object>._propertyContainerGetters[colName] = tpf; } return(pf); }
/// <summary> /// Initializes the specified property name. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="model">The model.</param> /// <param name="propertyName">Name of the property.</param> /// <param name="reference">The reference.</param> /// <param name="locator">The locator.</param> /// <param name="defaultValueFactory">The default value factory.</param> /// <returns>ValueContainer<T>.</returns> public static ValueContainer <T> Initialize <T>(this BindableBase model, string propertyName, ref Property <T> reference, ref Func <BindableBase, ValueContainer <T> > locator, Func <BindableBase, T> defaultValueFactory = null) { return(Initialize(model, propertyName, ref reference, ref locator, () => (defaultValueFactory != null) ? defaultValueFactory(model) : default(T))); }
/// <summary> /// 为CommandModel指定ViewModel /// </summary> /// <typeparam name="TCommand">ICommand实例的具体类型</typeparam> /// <typeparam name="TResource">附加资源类型</typeparam> /// <param name="cmdModel">CommandModel具体实例</param> /// <param name="viewModel">ViewModel具体实例</param> /// <returns>CommandModel<TCommand, TResource>.</returns> public static CommandModel <TCommand, TResource> WithViewModel <TCommand, TResource>(this CommandModel <TCommand, TResource> cmdModel, BindableBase viewModel) where TCommand : ICommand { //cmdModel. var cmd2 = cmdModel.CommandCore as ICommandWithViewModel; if (cmd2 != null) { cmd2.ViewModel = viewModel; } return(cmdModel); }
/// <summary> /// <para>Locate or create the value container of this model intances</para> /// <para>通过定位方法定位本Model实例中的值容器</para> /// </summary> /// <param name="model">Model intances/model 实例</param> /// <returns>Value Container of this property/值容器</returns> public ValueContainer <TProperty> LocateValueContainer(BindableBase model) { return(LocatorFunc(model)); }