I'm trying to bind to a Readonly
property with OneWayToSource
as mode, but it seems this cannot be done in XAML:
<controls:FlagThingy IsModified="{Binding FlagIsModified, ElementName=container, Mode=OneWayToSource}" />
I get:
The property 'FlagThingy.IsModified' cannot be set because it does not have an accessible set accessor.
IsModified
is a readonly DependencyProperty
on FlagThingy
. I want to bind that value to the FlagIsModified
property on the container.
To be clear:
FlagThingy.IsModified --> container.FlagIsModified ------ READONLY ----- ----- READWRITE --------
Is this possible using just XAML?
Update: Well, I fixed this case by setting the binding on the container and not on the FlagThingy
. But I'd still like to know if this is possible.
Data binding is a mechanism in XAML applications that provides a simple and easy way for Windows Runtime Apps using partial classes to display and interact with data. The management of data is entirely separated from the way the data is displayed in this mechanism.
OneWayToSource: The Source property will change if the target property is changed. If the user changes the TextProperty , the UserName property will take up the changed value. This again is of intermediate cost as the binding system watches only Target for changes.
ItemsSource can be data bound to any sequence that implements the IEnumerable interface, although the type of collection used does determine the way in which the control is updated when items are added to or removed.
Some research results for OneWayToSource...
Option # 1.
// Control definition public partial class FlagThingy : UserControl { public static readonly DependencyProperty IsModifiedProperty = DependencyProperty.Register("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata()); }
<controls:FlagThingy x:Name="_flagThingy" />
// Binding Code Binding binding = new Binding(); binding.Path = new PropertyPath("FlagIsModified"); binding.ElementName = "container"; binding.Mode = BindingMode.OneWayToSource; _flagThingy.SetBinding(FlagThingy.IsModifiedProperty, binding);
Option # 2
// Control definition public partial class FlagThingy : UserControl { public static readonly DependencyProperty IsModifiedProperty = DependencyProperty.Register("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata()); public bool IsModified { get { return (bool)GetValue(IsModifiedProperty); } set { throw new Exception("An attempt ot modify Read-Only property"); } } }
<controls:FlagThingy IsModified="{Binding Path=FlagIsModified, ElementName=container, Mode=OneWayToSource}" />
Option # 3 (True read-only dependency property)
System.ArgumentException: 'IsModified' property cannot be data-bound.
// Control definition public partial class FlagThingy : UserControl { private static readonly DependencyPropertyKey IsModifiedKey = DependencyProperty.RegisterReadOnly("IsModified", typeof(bool), typeof(FlagThingy), new PropertyMetadata()); public static readonly DependencyProperty IsModifiedProperty = IsModifiedKey.DependencyProperty; }
<controls:FlagThingy x:Name="_flagThingy" />
// Binding Code Same binding code...
Reflector gives the answer:
internal static BindingExpression CreateBindingExpression(DependencyObject d, DependencyProperty dp, Binding binding, BindingExpressionBase parent) { FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata; if (((fwMetaData != null) && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly) { throw new ArgumentException(System.Windows.SR.Get(System.Windows.SRID.PropertyNotBindable, new object[] { dp.Name }), "dp"); } ....
This is a limitation of WPF and it is by design. It is reported on Connect here:
OneWayToSource binding from a readonly dependency property
I made a solution to dynamically be able to push read-only dependency properties to the source called PushBinding
which I blogged about here. The example below does OneWayToSource
Bindings from the read-only DP's ActualWidth
and ActualHeight
to the Width and Height properties of the DataContext
<TextBlock Name="myTextBlock"> <pb:PushBindingManager.PushBindings> <pb:PushBinding TargetProperty="ActualHeight" Path="Height"/> <pb:PushBinding TargetProperty="ActualWidth" Path="Width"/> </pb:PushBindingManager.PushBindings> </TextBlock>
PushBinding
works by using two Dependency Properties, Listener and Mirror. Listener is bound OneWay
to the TargetProperty and in the PropertyChangedCallback
it updates the Mirror property which is bound OneWayToSource
to whatever was specified in the Binding.
Demo Project can be Downloaded Here.
It contains source code and short sample usage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With