<Controls:MyControl Mode="Mode1" Value="{Binding Path=Something}" />
The problem I have is that binding happens before Mode property is being set when I use this control in a data template of a ListView.
How do I make sure that Mode is always set before Value binding?
Binding path syntax. Use the Path property to specify the source value you want to bind to: In the simplest case, the Path property value is the name of the property of the source object to use for the binding, such as Path=PropertyName . Subproperties of a property can be specified by a similar syntax as in C#.
In One Way binding, source control updates the target control, which means if you change the value of the source control, it will update the value of the target control. So, in our example, if we change the value of the slider control, it will update the textbox value, as shown below.
Its very easy to do in WPF in comparison of windows Application programming. Two way binding is used when we want to update some controls property when some other related controls property change and when source property change the actual control also updates its property.
Data binding is a mechanism in WPF applications that provides a simple and easy way for Windows Runtime apps to display and interact with data. In this mechanism, the management of data is entirely separated from the way data. Data binding allows the flow of data between UI elements and data object on user interface.
What you could do is delay the binding, so you can be (almost) sure the mode value is set till then. There's a delay binding property in .net 4.5. Here's an article on how to simulate that in .net 4.0 Delay property on Binding from .Net 4.5 in .Net 4.0
I personally would implement that in a viewModel (MVVM), where this kind of issue is rather simple to resolve. Make two properties Mode and Something. When mode changes it should trigger that the "Something" property was changed also ( via INotifyPropertyChanged Interface).
class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string _mode;
public string Mode
{
get { return _mode; }
set
{
_mode = value;
OnPropertyChanged("Mode");
// OnPropertyChanged("Something");
// or build up via a method:
// Something = DetermineFromMode(Mode);
}
}
private string _something;
public string Something
{
get { return _something; }
set
{
_something = value;
OnPropertyChanged("Something");
}
}
}
Have you tried raising the property changed event for your property "Something" when Mode of your control get set? You can get the property "Something" in you control like this -
Binding binding = BindingOperations.GetBindingExpression(this, this.Value).ParentBindingBase;
String propertyToRefresh = binding.Path.Path;
(this.DataContext as ViewModel).OnPropertyChange(propertyToRefresh);
I am assuming that the DataContext of your Control is your ViewModel's instance which implements INotifyPropertyChangedInterface.
In case your Viemodel class OnPropertyChange method is not public or you don't have reference to your ViewModel class in your control. You can simply call the UpdateTarget() on your BindingExpression like this (as suggested by Thomas Levesque) -
BindingExpression binding = BindingOperations.GetBindingExpression(this, this.Value);
binding.UpdateTarget();
(I know this is old but I ran into this problem today so I was forced to do some investigation)
It appears that binding occurs in the order the DependencyProperties are defined.
For instance, in MyControl.cs
public int Mode { get => (int)GetValue(ModeProperty); set => SetValue(ModeProperty, value); }
public static readonly DependencyProperty ModeProperty
= DependencyProperty.Register(nameof(Mode), typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(new PropertyChangedCallback(Mode_Changed)));
public string Result { get => (string)GetValue(ResultProperty); set => SetValue(ResultProperty, value); }
public static readonly DependencyProperty ResultProperty
= DependencyProperty.Register(nameof(Result), typeof(string), typeof(MyControl),
new FrameworkPropertyMetadata(new PropertyChangedCallback(Result_Changed)));
private static void Mode_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//Mode changed. Update display.
}
private static void Result_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//Result changed. Update display.
}
And the XAML:
<controls:MyControl Result="You passed!"
Mode="3" />
Because Mode
is defined as a dependency property before Result
, Mode
will be set first. The order in which you assign the values in the XAML is ignored.
So in theory, to answer your question, make sure the Mode property is defined first. This solved my issue.
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