private static void RefreshBinding(AvaloniaObject target, AvaloniaProperty property)
 {
     if (target.GetValue(property) is IBinding binding)
     {
         target.Bind(property, binding);
     }
 }
Exemplo n.º 2
0
 /// <summary>
 /// Initializes a new binding.
 /// </summary>
 /// <param name="avaloniaObject">The <see cref="AvaloniaObject"/> to apply the new binding to.</param>
 /// <param name="avaloniaProperty">The <see cref="AvaloniaProperty{TValue}"/> the new binding should be applied to.</param>
 /// <param name="defaultValue">The default value of the <paramref name="avaloniaProperty"/> at <c>1.0</c> scaling.</param>
 public virtual void Initialize(AvaloniaObject avaloniaObject, AvaloniaProperty <T> avaloniaProperty, T defaultValue)
 {
     if (!isInitialized)
     {
         subscription  = avaloniaObject.Bind(avaloniaProperty, source);
         DefaultValue  = defaultValue;
         isInitialized = true;
     }
 }
Exemplo n.º 3
0
        private void AddBinding <T>(string modelFieldName,
                                    AvaloniaObject control,
                                    AvaloniaProperty <T> property,
                                    bool isTwoWayDataBinding = false)
        {
            // (ideas from here)[http://avaloniaui.net/docs/binding/binding-from-code]
            var bindingSource = new Subject <T>();

            control.Bind <T>(property, bindingSource.AsObservable());

            bool   bindingIsDataContext = false;
            object dataContext          = null;

            // does model contain a datacontext???
            if (this.Model.HasKey(SpecialModelKeys.DataContext))
            {
                // bind to the data context
                dataContext = this.Model[SpecialModelKeys.DataContext];

                if (dataContext is System.ComponentModel.INotifyPropertyChanged prop)
                {
                    // It's INotifyPropertyChanged so set this as handled
                    bindingIsDataContext = true;

                    // need to fire it's current value.  Then start watching for changes
                    var currentValue = getDataContextValue(dataContext, modelFieldName);
                    log.Debug(
                        $"AddBinding-Model Value Change [*Initial* Field: {modelFieldName}; New Value: {currentValue}]");
                    FireOnNextWithValue <T>(bindingSource, currentValue);

                    prop.PropertyChanged += (_s, _args) => {
                        if (string.Equals(_args.PropertyName, modelFieldName, StringComparison.OrdinalIgnoreCase))
                        {
                            var newCurrentValue = getDataContextValue(dataContext, modelFieldName);
                            log.Debug($"AddBinding-Model Value Change [Field: {modelFieldName}; New Value: {newCurrentValue}]");
                            FireOnNextWithValue <T>(bindingSource, newCurrentValue);
                        }
                    };
                }
                else
                {
                    /*
                     * !!REMEMBER!! You can use the bindabledictionary
                     * If you don't want to go to the trouble of implementing INotifyPropertyChanged just have your items use BindableDictionary and it's pretty easy
                     */
                    throw new Exception(
                              $"Special DataContext used in model, but DataContext is not INotifyPropertyChanged.  [modelFileName: {modelFieldName}] Type given is {dataContext?.GetType().Name ?? "null"}.  There is no way to read properties without INotifyPropertyChanged");
                }
            }

            if (!bindingIsDataContext)
            {
                notifyOnModelChange(modelFieldName, (val) =>
                {
                    FireOnNext <T>(bindingSource, modelFieldName);
                });
            }
            // If they say two way then we setup a watch on the property observable and apply the values back to the model
            if (isTwoWayDataBinding)
            {
                // monitor for Property changes on control
                var controlValueChangesObservable = control.GetObservable(property);

                controlValueChangesObservable.Subscribe(newVal =>
                {
                    if (newVal == null)
                    {
                        // there is never a situation where the UI would need to make a model property null right???
                        return;
                    }

                    log.Debug($"AddBinding-TwoWay-Control Value Change [Control Property: {property.Name}; Field: {modelFieldName}; New Value: {newVal}]");
                    setModelValue(modelFieldName, newVal);
                });
            }


            // end of AddBinding
        }