/// <summary> /// Binds to the specified child <paramref name="binding"/> of this binding. /// </summary> /// <remarks> /// This can be used to bind to child objects of your view model, for example /// <code>model.SomeProperty.ChildProperty</code>. /// </remarks> /// <example> /// Use this like so: /// <code> /// public class MyChild { public SomeChildProperty { get; set; } } /// public class MyModel { public ChildObject { get; set; } } /// /// var model = new MyModel(); /// Binding.Property(model, (MyModel m) => m.ChildObject).Child(Binding.Property("SomeChildProperty")); /// </code> /// </example> /// <returns>The binding to the child property accessed through the current binding.</returns> /// <param name="binding">Binding to get the child value from this binding.</param> /// <typeparam name="TNewValue">The type of the child property value.</typeparam> public new BindableBinding <T, TNewValue> Child <TNewValue>(IndirectBinding <TNewValue> binding) { object childBindingReference = null; EventHandler <EventArgs> eventHandler = null; EventHandler <EventArgs> valueChanged = (sender, e) => { binding.RemoveValueChangedHandler(childBindingReference, eventHandler); eventHandler?.Invoke(sender, e); childBindingReference = binding.AddValueChangedHandler(DataValue, eventHandler); }; return(new BindableBinding <T, TNewValue>( DataItem, c => binding.GetValue(DataValue), (c, v) => binding.SetValue(DataValue, v), addChangeEvent: (c, ev) => { eventHandler = ev; DataValueChanged += valueChanged; childBindingReference = binding.AddValueChangedHandler(DataValue, ev); }, removeChangeEvent: (c, ev) => { binding.RemoveValueChangedHandler(childBindingReference, ev); DataValueChanged -= valueChanged; } )); }
/// <summary> /// Binds to the specified child <paramref name="binding"/> of this binding. /// </summary> /// <remarks> /// This can be used to bind to child objects of your view model, for example /// <code>model.SomeProperty.ChildProperty</code>. /// </remarks> /// <example> /// Use this like so: /// <code> /// public class MyChild { public SomeChildProperty { get; set; } } /// public class MyModel { public ChildObject { get; set; } } /// /// var model = new MyModel(); /// Binding.Property(model, (MyModel m) => m.ChildObject).Child(Binding.Property("SomeChildProperty")); /// </code> /// </example> /// <returns>The binding to the child property accessed through the current binding.</returns> /// <param name="binding">Binding to get the child value from this binding.</param> /// <typeparam name="TValue">The type of the child property value.</typeparam> public DirectBinding <TValue> Child <TValue>(IndirectBinding <TValue> binding) { object childBindingReference = null; EventHandler <EventArgs> eventHandler = null; EventHandler <EventArgs> valueChanged = (sender, e) => { binding.RemoveValueChangedHandler(childBindingReference, eventHandler); eventHandler?.Invoke(sender, e); childBindingReference = binding.AddValueChangedHandler(DataValue, eventHandler); }; return(new DelegateBinding <TValue>( () => binding.GetValue(DataValue), v => binding.SetValue(DataValue, v), addChangeEvent: ev => { eventHandler = ev; DataValueChanged += valueChanged; childBindingReference = binding.AddValueChangedHandler(DataValue, ev); }, removeChangeEvent: ev => { binding.RemoveValueChangedHandler(childBindingReference, ev); DataValueChanged -= valueChanged; } )); }
/// <summary> /// Binds to the specified child <paramref name="binding"/> of this binding. /// </summary> /// <remarks> /// This can be used to bind to child objects of your view model, for example /// <code>model.SomeProperty.ChildProperty</code>. /// </remarks> /// <example> /// Use this like so: /// <code> /// public class MyChild { public SomeChildProperty { get; set; } } /// public class MyModel { public ChildObject { get; set; } } /// /// Binding.Property((MyModel m) => m.ChildObject).Child(Binding.Property("SomeChildProperty")); /// </code> /// </example> /// <returns>The binding to the child property accessed through the current binding.</returns> /// <param name="binding">Binding to get the child value from this binding.</param> /// <typeparam name="TNewValue">The type of the child property value.</typeparam> public IndirectBinding <TNewValue> Child <TNewValue>(IndirectBinding <TNewValue> binding) { object bindingReference = null; object childBindingReference = null; object context = null; EventHandler <EventArgs> eventHandler = null; EventHandler <EventArgs> valueChanged = (sender, e) => { binding.RemoveValueChangedHandler(childBindingReference, eventHandler); eventHandler?.Invoke(sender, e); childBindingReference = binding.AddValueChangedHandler(GetValue(context), eventHandler); }; return(new DelegateBinding <object, TNewValue>( c => binding.GetValue(GetValue(context = c)), (c, v) => binding.SetValue(GetValue(context = c), v), addChangeEvent: (c, ev) => { context = c; eventHandler = ev; bindingReference = AddValueChangedHandler(c, valueChanged); childBindingReference = binding.AddValueChangedHandler(GetValue(c), ev); }, removeChangeEvent: (c, ev) => { binding.RemoveValueChangedHandler(childBindingReference, ev); RemoveValueChangedHandler(bindingReference, valueChanged); } )); }
/// <inheritdoc/> protected override void InternalSetValue(object dataItem, TChild value) { if (IsStruct) { // box value to object so it is passed by reference object childItem = _parent.GetValue(dataItem); // set the child value _child.SetValue(childItem, value); // set value back since it is a struct _parent.SetValue(dataItem, (TParent)childItem); } else { var childItem = _parent.GetValue(dataItem); _child.SetValue(childItem, value); } }
/// <summary> /// Binds to the specified child <paramref name="binding"/> of this binding. /// </summary> /// <remarks> /// This can be used to bind to child objects of your view model, for example /// <code>model.SomeProperty.ChildProperty</code>. /// </remarks> /// <example> /// Use this like so: /// <code> /// public class MyChild { public SomeChildProperty { get; set; } } /// public class MyModel { public ChildObject { get; set; } } /// /// var model = new MyModel(); /// Binding.Property(model, (MyModel m) => m.ChildObject).Child(Binding.Property("SomeChildProperty")); /// </code> /// </example> /// <returns>The binding to the child property accessed through the current binding.</returns> /// <param name="binding">Binding to get the child value from this binding.</param> /// <typeparam name="TValue">The type of the child property value.</typeparam> public DirectBinding <TValue> Child <TValue>(IndirectBinding <TValue> binding) { object childBindingReference = null; EventHandler <EventArgs> eventHandler = null; void valueChanged(object sender, EventArgs e) { binding.RemoveValueChangedHandler(childBindingReference, eventHandler); eventHandler?.Invoke(sender, e); childBindingReference = binding.AddValueChangedHandler(DataValue, eventHandler); } void setValueStruct(TValue v) { object parentValue = DataValue; binding.SetValue(parentValue, v); DataValue = (T)parentValue; } void setValueObject(TValue v) => binding.SetValue(DataValue, v); var isStruct = typeof(T).GetTypeInfo().IsValueType; return(new DelegateBinding <TValue>( () => binding.GetValue(DataValue), isStruct ? (Action <TValue>)setValueStruct : setValueObject, addChangeEvent: ev => { eventHandler = ev; DataValueChanged += valueChanged; childBindingReference = binding.AddValueChangedHandler(DataValue, ev); }, removeChangeEvent: ev => { binding.RemoveValueChangedHandler(childBindingReference, ev); DataValueChanged -= valueChanged; } )); }
/// <inheritdoc/> protected override void InternalSetValue(object dataItem, TChild value) { if (IsStruct) { // box value to object so it is passed by reference object childItem = _parent.GetValue(dataItem); // set the child value _child.SetValue(childItem, value); // set value back since it is a struct _parent.SetValue(dataItem, (TParent)childItem); } else { var childItem = _parent.GetValue(dataItem); _child.SetValue(childItem, value); // if this is an object binding, check to see if we are a boxed struct var isStruct = typeof(TParent) == typeof(object) && childItem?.GetType().GetTypeInfo().IsValueType == true; if (isStruct) { _parent.SetValue(dataItem, childItem); } } }