I have a OneWayToSource binding that is not behaving as I expected when I set the DataContext of the target control. The property of the source is being set to default inste
You need Attached property:
public static readonly DependencyProperty OneWaySourceRaiseProperty = DependencyProperty.RegisterAttached("OneWaySourceRaise", typeof(object), typeof(FrameworkElementExtended), new FrameworkPropertyMetadata(OneWaySourceRaiseChanged));
public static object GetOneWaySourceRaise(DependencyObject o)
{
return o.GetValue(OneWaySourceRaiseProperty);
}
public static void SetOneWaySourceRaise(DependencyObject o, object value)
{
o.SetValue(OneWaySourceRaiseProperty, value);
}
private static void OneWaySourceRaiseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue == null)
return;
var target = (FrameworkElement)d;
target.Dispatcher.InvokeAsync(() =>
{
var bindings = target.GetBindings().Where(i => i.ParentBinding?.Mode == BindingMode.OneWayToSource).ToArray();
foreach (var i in bindings)
{
i.DataItem.SetProperty(i.ParentBinding.Path.Path, d.GetValue(i.TargetProperty));
}
});
And set binding in XAML:
extendends:FrameworkElementExtended.OneWaySourceRaise="{Binding}"
where {Binding} - is binding to DataContext.
You need:
public static IEnumerable GetBindings(this T element, Func func = null) where T : DependencyObject
{
var properties = element.GetType().GetDependencyProperties();
foreach (var i in properties)
{
var binding = BindingOperations.GetBindingExpression(element, i);
if (binding == null)
continue;
yield return binding;
}
}
private static readonly ConcurrentDictionary DependencyProperties = new ConcurrentDictionary();
public static DependencyProperty[] GetDependencyProperties(this Type type)
{
return DependencyProperties.GetOrAdd(type, t =>
{
var properties = GetDependencyProperties(TypeDescriptor.GetProperties(type, new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.All) }));
return properties.ToArray();
});
}
private static IEnumerable GetDependencyProperties(PropertyDescriptorCollection collection)
{
if (collection == null)
yield break;
foreach (PropertyDescriptor i in collection)
{
var dpd = DependencyPropertyDescriptor.FromProperty(i);
if (dpd == null)
continue;
yield return dpd.DependencyProperty;
}
}